Search Unity

[SOLVED] Detect what direction character is facing

Discussion in 'Scripting' started by Collin__Patrick, Feb 14, 2016.

  1. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I have a character walking around a sphere with gravity much like a planet. Everything works but when the character goes past the equator of the sphere the camera and gravity get weird and the player eventually falls off.

    I want to rotate the sphere against the character movement so the character is always upright and it feels like the world is moving whenever the player moves. Because I use "A" and "D" to rotate the character I cannot just recycle the character movement script and make the sphere do the opposite. I must be able to detect what direction the player is facing and rotate the sphere accordingly.

    How would I detect the direction the player is facing? As always, help is much appreciated.
     
  2. frilanski

    frilanski

    Joined:
    Oct 19, 2013
    Posts:
    11
    Facing direction of your player can be found by looking at the transform.rotation and as you seem to only be looking left and right you would use transform.rotation.y to check the y axis of your player (assuming the script is attached to your player).

    not sure that helped but what if you keep the player still and rotate the planet underneath it and then only rotate the player with "A" & "D" (unless you want to go different places)
     
  3. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I am not quite sure as to what you are getting at. could you give an example?

    This is my Characters movement script:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerController : MonoBehaviour {
    5.  
    6.     public float rotateSpeed;
    7.     public float forwardSpeed;
    8.     private CharacterController playerController;
    9.  
    10.     // Use this for initialization
    11.     void Start () {
    12.         playerController = GetComponent<CharacterController> ();
    13.     }
    14.  
    15.     // Update is called once per frame
    16.     void Update () {
    17.     if (Input.GetKeyDown("space") && playerController.isGrounded) {
    18.             playerController.Move(Vector3.up);
    19.         }
    20.  
    21.         transform.Rotate (0, Input.GetAxis ("Horizontal") * rotateSpeed, 0);
    22.         Vector3 forward = transform.TransformDirection (Vector3.forward);
    23.         float speed = forwardSpeed * Input.GetAxis ("Vertical");
    24.         playerController.SimpleMove (speed * forward);
    25.     }
    26.  
    27. }
    This is what I have attached to my sphere:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SphereRotate : MonoBehaviour {
    5.  
    6.     public float moveSpeed = 100.0f;
    7.  
    8.     // Use this for initialization
    9.     void Start () {
    10.      
    11.     }
    12.  
    13.     // Update is called once per frame
    14.     void Update () {
    15.         if (Input.GetKey ("w")) {
    16.             transform.Rotate((Vector3.forward)* moveSpeed * Time.deltaTime);
    17.         }
    18.         if (Input.GetKey ("s")) {
    19.             transform.Rotate((Vector3.back)* moveSpeed * Time.deltaTime);
    20.         }
    21.         if (Input.GetKey ("a")) {
    22.             transform.Rotate((Vector3.left)* moveSpeed * Time.deltaTime);
    23.         }
    24.         if (Input.GetKey ("d")) {
    25.             transform.Rotate((Vector3.right)* moveSpeed * Time.deltaTime);
    26.         }
    27. }
    28. }
     
    Last edited: Feb 14, 2016
  4. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
  5. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    Moving both seems overly complicated, I'd stick with just one of them. Either move the character around the sphere and have the camera follow to make it appear as the player is always on top, or keep the character in place and just rotate the sphere.

    Using the built-in gravity doesn't really make sense with a sphere world as it only works downwards and not towards the center of the sphere, so it'll probably be better to just turn it off and apply an inwards force manually (if you even need it).

    I cobbled together an example of the latter for you, hope this helps

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Player : MonoBehaviour
    6. {
    7.     [SerializeField] private float m_TurnSpeed = 100f;
    8.     [SerializeField] private float m_MoveSpeed = 100f;
    9.     [SerializeField] private Transform m_SphereTransform;
    10.  
    11.     void Update()
    12.     {
    13.         float turn = Input.GetAxis("Horizontal");
    14.         transform.Rotate(transform.up, turn * m_TurnSpeed * Time.deltaTime);
    15.         float move = Input.GetAxis("Vertical");
    16.         m_SphereTransform.Rotate(-transform.right, move * m_MoveSpeed * Time.deltaTime, Space.World);
    17.     }
    18. }
    19.  
     

    Attached Files:

  6. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    Wow thanks! That works perfectly.
     
  7. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    Would you mind also answering another question?

    Now that the sphere works I started adding things to it to make it look more lively. I came across a problem where whenever the player collides with something and continues to walk into it, the player slowly gets pushed with the sphere creating problems with the camera and sphere its self. I made a script that fixes the problem but creates a new one. After the player collides with an object of a certain tag, the sphere stops moving and and wont move until the player stops colliding. My problem is that if the player continues to collide with an object it will eventually get stuck preventing any movement. How can I fix this?

    Collision Script:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerCollision : MonoBehaviour {
    5.  
    6.     private float force = 100;
    7.  
    8.     void OnCollisionEnter(Collision col){
    9.         if (col.gameObject.tag == "Environment") {
    10.             Player.m_MoveSpeed = 0f;
    11.             Vector3 dir = col.contacts[0].point - transform.position;
    12.             dir = -dir.normalized;
    13.             gameObject.GetComponent<Rigidbody>().AddForce(dir*force);
    14.         } else if (col.gameObject.tag != "Environment") {
    15.             Player.m_MoveSpeed = 5f;
    16.         }
    17.     }
    18. }
     
  8. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    I would think you could get around this by just setting some restrictions on the rigidbody of the player, only allowing it to move up and down on the Y axis.

    If you just want the player to follow the shape of the sphere however, it will likely skip and jump as it moves over obstacles, if you are using physics. I don't know what you're going for, but it might be better to instead just use a raycast from above the sphere and down, and move the player to the position where it hits, bypassing physics altogether.
     
  9. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    If I put position constraints on the rigidbody the player will just go through things instead of stopping because it hit a wall. This makes it hard to add things to the sphere such as bodys of water or mountains that the player cannot cross. I am using 3rd person controls and don't really want to do point and click. Just for context on what I am doing, the player walks around a sphere which is the planet they are on. The sphere acts as a fast travel map so whenever the player walks to an accessible region they will load into that region in a flat to scale (sculpted terrain) area.
     
    Last edited: Feb 15, 2016
  10. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    I'd still put constraints on the player, and then use physics to rotate the world, so that the world stops when the player hits a wall.

    Get a reference to the sphere rigidbody instead of the transform, and use either AddTorque, angularVelocity or MoveRotation to rotate the sphere.
     
  11. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    transform.forward
     
  12. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    That problem was solved long ago. If you have any suggestions for the new one that came up, I would be happy to hear your input.
     
  13. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    If you can, could you edit the player script in the package you linked earlier? I am not very familiar with collision and physics in unity.
     
  14. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    Yeah okay, hope this helps

    EDIT: Ooops, I forgot one thing, please replace "void Update()" with "void FixedUpdate()", all physics should be applied in FixedUpdate and not in Update.
     

    Attached Files:

    Last edited: Feb 16, 2016
  15. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I am not sure if I am doing this correctly. I applied the new script but the problem still exists. With constraints on or off the player just passes through any object.
     
  16. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    Does the example I gave you work as you'd expect? Are you sure there is a rigidbody and colliders on your objects? If my scene works for you, try taking a look at how it is set up in the scene with rigidbodies and colliders.
     
  17. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    Ok, after further investigation I figured out that I had the players collider on the empty gameobject containing the player rather than on the player its self, the rigidbody was on the player and not the empty game object, and the is kinematic was turned on for the sphere. It works beautifully now.
     
  18. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    Great, glad to hear you got it working, good luck with your game.