Jump to content
Unity Insider Forum

Intelligente 3D Platformer Steuerung


Garzec

Recommended Posts

Hallo,

ich arbeite grade an einer Steuerung für 3D Platformer wie z.B. Super Mario 64, Banjo Kazooie, Zelda oder Spyro etc. etc. da gab es damals ja einige.

Nun habe ich die Steuerung schon ganz anständig gebastelt, der Spieler bewegt sich relativ zur Kamera.

Die Kamera

public class CameraMovement : MonoBehaviour {

    float inputHorizontal;
    float inputVertical;
    float sensitivityX = 4;
    float sensitivityY = 2;
    float horizontalRotation;
    float verticalRotation;
    float yMin = 0;
    float yMax = 80;
    float distanceFromTarget = 10;
    float rotationSmoothTime = 0.12f;
    Vector3 currentRotation;
    Vector3 rotationSmoothVelocity;
    GameObject playerObject;

    private void Start()
    {
        playerObject = GameObject.FindGameObjectWithTag(StringCollection.PLAYER);
    }

    private void LateUpdate()
    {
        if (playerObject != null)
        {
            horizontalRotation += Input.GetAxisRaw(StringCollection.MOUSE_X) * sensitivityX;
            verticalRotation -= Input.GetAxisRaw(StringCollection.MOUSE_Y) * sensitivityY;
            verticalRotation = Mathf.Clamp(verticalRotation, yMin, yMax);

            currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(verticalRotation, horizontalRotation), ref rotationSmoothVelocity, rotationSmoothTime);

            transform.eulerAngles = currentRotation;

            transform.position = playerObject.transform.position - transform.forward * distanceFromTarget;
        }
    }
}

Das Spielerscript:

public class PlayerMovement : Creature
{
    private float movementSpeed = 8;
    private float currentMovementSpeed;
    private float speedSmoothTime = 0.1f;
    private float turnSmoothTime = 0.1f;
    private float inputHorizontal;
    private float inputVertical;
    private float jumpPower = 10;
    private float airControlPercentage = 0.2f;
    private bool isGrounded;
    private bool jumpPressed;
    private float turnSmoothVelocity;
    private float speedSmoothVelocity;
    Rigidbody playerRigid;
    Transform cameraTransform;

    private void Start()
    {
        playerRigid = gameObject.GetComponent<Rigidbody>();
        cameraTransform = Camera.main.gameObject.transform;
    }

    private void Update()
    {
        if (Input.GetButtonDown(StringCollection.JUMP))
            jumpPressed = true;
    }

    private void FixedUpdate()
    {
        isGrounded = GroundCheck();

        Vector2 inputDirection = (new Vector2(Input.GetAxisRaw(StringCollection.HORIZONTAL), Input.GetAxisRaw(StringCollection.VERTICAL))).normalized;

        if (isGrounded && jumpPressed)
            playerRigid.velocity = new Vector3(playerRigid.velocity.x, jumpPower, playerRigid.velocity.z);

        jumpPressed = false;

        if (inputDirection != Vector2.zero)
            transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, Mathf.Atan2(inputDirection.x, inputDirection.y) * Mathf.Rad2Deg + cameraTransform.eulerAngles.y, ref turnSmoothVelocity, GetModifiedSmoothTime(turnSmoothTime));

        currentMovementSpeed = Mathf.SmoothDamp(currentMovementSpeed, movementSpeed * inputDirection.magnitude, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));

        playerRigid.velocity = transform.forward * currentMovementSpeed + Vector3.up * playerRigid.velocity.y;

        currentMovementSpeed = (new Vector2(playerRigid.velocity.x, playerRigid.velocity.z)).magnitude;
    }

    private float GetModifiedSmoothTime(float smoothTime)
    {
        if (isGrounded)
            return smoothTime;

        if (airControlPercentage == 0)
            return float.MaxValue;

        return smoothTime / airControlPercentage;
    }

    private bool GroundCheck()
    {
        return true;
    }
}

Nun ist es mit dieser Steuerung nicht möglich, auf die Kamera zuzulaufen oder sich nach links/rechts zu bewegen und die Kamera bleibt währenddessen stehen.

Also war unter anderem mein Gedanke, die Steuerung so umzubauen, dass die Kamera dem Spieler nur noch folgt, sobald er sich weit entfernt hat. Ansonsten steht die Kamera immer auf 

transform.lookAt(playerObject);

Das wäre aber glaube ich unpassend, da die Kamera bei Wänden stehen bleibt und durch die Wand guckt.Ich müsste also permanent einen Raycast zum Spieler feuern, um zu gucken, ob sich etwas im Weg befindet und dann reagieren.

Da bin ich mir aber generell unsicher, wie die Spiele von damals genau umgesetzt worden sind. Hat jemand eine Idee für mein bereits vorhandenes Script, ob ich dieses modifizieren kann? Also ich glaube ich habe mit dem Script schon den richtigen Weg eingeschlagen, aber zur Kamera hin oder seitlich laufen und die Kamera bleibt stehen, ist mit diesem Code nicht möglich.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich würde das Verhalten der Kamera von der Steuerung trennen.
Sprich: 

vor 22 Stunden schrieb Garzec:

Also war unter anderem mein Gedanke, die Steuerung so umzubauen, dass die Kamera dem Spieler nur noch folgt, sobald er sich weit entfernt hat.

Wie die Entwickler das damals gemacht haben, kann ich dir nicht sagen.

Ich würde keinen Ray casten, sondern irgendwas mit einem SphereCast machen, sodass du nicht n-viele Rays hast, sondern nur 2 oder 3 Spheres castest.

Also würde ich ein CameraBehaviour.cs oder ähnlich erstellen, an die Kamera anfügen und dort die Kamera-Logik basteln.

Eine Entfernung oder ein Radius definieren, in dem der Character beliebig rumhüpfen kann, ohne dass sich die Kamera bewegt. Verlässt der Character den Radius oder ist zu weit entfernt, bewegt sich die Kamera.

Das mit den Wänden würde ich dann anschließend seperat lösen. Irgendwie die CameraBounds auslesen und abfragen, ob diese geblockt werden oder in einer Wand stecken. Das geht bestimmt, habe ich selber aber noch nicht benötigt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...