I want to make the control of the player, as in the game "Overcooked".

Trailer with gameplay.

My current player management.

enter image description here

PlayerController.cs

using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerControllerTransform : MonoBehaviour { private string moveInputAxis = "Vertical"; private string turnInputAxis = "Horizontal"; public float rotationRate = 360f; public float moveSpeed = 1; // Use this for initialization void Start () { } // Update is called once per frame void Update () { float moveAxis = Input.GetAxis (moveInputAxis); float turnAxis = Input.GetAxis (turnInputAxis); //Обновляет каждый кадр наше положение и поворот ApplyInput (moveAxis, turnAxis); } private void ApplyInput(float moveInput, float turnInput) { Move (moveInput); Turn(turnInput); } private void Move(float input) { transform.Translate (Vector3.forward*input*moveSpeed);//Можно добавить Time.DeltaTime } private void Turn(float input) { transform.Rotate (0,input * rotationRate * Time.deltaTime,0); } } 

What is the problem. In the game where I clicked (WASD), I turned my nose and went there. (As I understood it) At the moment I have control more like a machine control. AD-responsible for turning. W-forward, S-back.

In the end, I want to make a control similar to the game.

ps Another video gameplay to understand better game management.

Thanks for attention.

    1 answer 1

    Generally with the questions "How game X made Y" it is better to contact the developers themselves. And not because someone is “too lazy” to answer such questions, but simply because it is often quite difficult to recreate something from another 1v1 game.


    Surely this can be done in another way, but I decided to go through 2 stages:

    1. character rotation depending on input
    2. Moving a character through transform.forward , good character in this game always moves only face forward

    Data input

    Everything is as simple as possible and does not differ from the variant in question, but I write down the whole thing in a vector, in order to get corners and other necessary things through it:

     private Vector3 moveVector; ... void HandleInput() { moveVector.x = Input.GetAxis("Horizontal"); moveVector.z = Input.GetAxis("Vertical"); } 

    Rotation

    It would seem you can just use

     transform.Rotate(Vector3.up, Vector3.Angle(transform.forward, moveVector)); 

    But Vector3.Angle returns the smallest angle between the vectors, i.e. from 0 to 180, which leads to these results when rotating by an angle from 0 to 360:

    enter image description here

    One of the ways out of this situation is to write your own function for determining the angle between vectors for a range of angles [0..360]:

     float Angle360(Vector3 from, Vector3 to, Vector3 right) { float angle = Vector3.Angle(from, to); return (Vector3.Angle(right, to) > 90f) ? 360f - angle : angle; } 

    This function is very simple to find in Google - I do not want to overload the question with its explanation.

    And then we apply the whole thing in Update :

     void Update () { HandleInput(); transform.Rotate(Vector3.up, Angle360(transform.forward, moveVector, transform.right)); } 

    And we get the rotation we almost need:

    enter image description here


    Move

    Everything is almost elementary: it uses Transform.Translate , not forgetting to add a variable for speed:

     public float speed = 2f; ... transform.Translate(transform.forward * speed * Time.deltaTime, Space.World); 

    This code will constantly move the object in the direction of its local "straight." But we want to move it only when the user enters.

    The logical way out is to use the moveVector vector moveVector , having previously normalized it, in order to get a value in the range [0..1]:

     transform.Translate( moveVector.normalized.sqrMagnitude * transform.forward * speed * Time.deltaTime, Space.World ); 

    In this case, you can use the module square simply because the module square will always be either 0 or 1 , and sqrt(1) == 1/-1 , sqrt(0) == 0 . -1 for obvious reasons, we are not worried.

    But purely on sensations - I did not measure the results, it's easier to do without this module at all and do this:

     float Moves() { if(moveVector.x != 0 || moveVector.z != 0) { return 1f; } else { return 0f; } } 

    It is worth noting that this method will always produce a motion vector 1. If the game supports gamepads, where joysticks can output values ​​along both [0..1] axes, it is better to use a vector module.

    And substituting the result of this method in Translate .


    In the end, we got some such component:

     public class OvercookedLikeMovement : MonoBehaviour { public float speed = 2f; private Vector3 moveVector; void Update () { HandleInput(); transform.Rotate(Vector3.up, Angle360(transform.forward, moveVector, transform.right)); transform.Translate( Moves() * transform.forward * speed * Time.deltaTime, Space.World ); } void HandleInput() { moveVector.x = Input.GetAxis("Horizontal"); moveVector.z = Input.GetAxis("Vertical"); } float Moves() { if(moveVector.x != 0 || moveVector.z != 0) return 1f; else return 0f; } float Angle360(Vector3 from, Vector3 to, Vector3 right) { float angle = Vector3.Angle(from, to); return (Vector3.Angle(right, to) > 90f) ? 360f - angle : angle; } } 

    Result in Unity:

    enter image description here


    PS

    It is seen that the object sometimes moves jerky. The reason for this is a sharp change in the angle of rotation of the object, this is not a bug, but the logical result of the code is higher and not done without interpolation.

    What would I do if I were you?

    I would look in the direction of Tween engines for Unity, with which you can smooth the whole thing and make it more natural, or something. But the result at the moment, as for me, is very similar to OverCooked.

    • Wow I am so delighted with your answer. Unfortunately, I already sleep on the go, but I will definitely read everything in the morning. ps Gifs with the result, cool. - Artik Slayer
    • Very good answer, my respect, sir) - Andrew
    • @ArtikSlayer was glad to help :) - RiotBr3aker
    • @RiotBr3aker By the way, you can duplicate your answer here for I asked here earlier. Extra points + help others. + just under ps can offer others to improve your version, etc. Thanks again to you) gamedev.stackexchange.com/questions/167070/… - Artik Slayer 5:38 pm