Search Unity

Make collider work only if player faced in certain direction.

Discussion in 'Scripting' started by cristo, May 25, 2017.

  1. cristo

    cristo

    Joined:
    Dec 31, 2013
    Posts:
    265
    Just trying to make a collider work only if player is faced in a certain direction. Not sure where I'm going wrong. Any advice would be great. Hopefully you can see what I mean from the code.


    Code (CSharp):
    1.  
    2. public class ScientistVanish : MonoBehaviour {
    3.  
    4.     public GameObject Scientist;
    5.     public GameObject Pplayer;
    6.     public float yRotation = -3;
    7.  
    8.  
    9.  
    10.     // Use this for initialization
    11.     void Start () {
    12.        
    13.     }
    14.    
    15.     void OnTriggerEnter (Collider Pplayer) {
    16.         if (Pplayer.gameObject.tag == "Player" && Pplayer.transform.rotation.y < yRotation)
    17.         {
    18.             Scientist.SetActive(false);
    19.         }
    20.        
    21.     }
    22. }
    23.  
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    1) use CompareTag, not tag ==... nothing to do with your problem, it's just far more performant

    2) Why is there a field named 'Pplayer' and you also have a parameter called 'Pplayer'? This makes for confusing naming conventions.

    3) transform.rotation returns a Quaternion, the y component is going to be a value from -1 to 1. You may want 'eulerAngles' instead... but even then, there's no guarantee that the value will come out in the range you want since 270 and -90 are the same thing.
     
    cristo likes this.
  3. cristo

    cristo

    Joined:
    Dec 31, 2013
    Posts:
    265
    Cheers thanks for your insight.


     
  4. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    I would use a Dot product.

    Dot(currentForward,targetForward) basically means it performs a dot product comparison on how similar the currentforward is with the targetForward (in this example I'll use east). Dot will return a value from 1 to -1, where 1 is if the player is looking in the exact same direction (looking east), -1 means the player is looking in the exact opposite direction (looking west), and where 0 means they are looking exactly perpendicular (ie. north or south).

    I prefer to use angle limits as they are more intuitive in the inspector (when you're looking for that specific angle), but in code I'll convert that value to a Dot Threshold and compare against that.


    Code (CSharp):
    1.  
    2.     [Range(0,180)] public float angle = 90;
    3.     public Gameobject Scientist;
    4.  
    5.    
    6.     void OnTriggerEnter (Collider player)
    7.     {
    8.         if (!player.CompareTag("Player")) return;
    9.  
    10.         if(!LookingAt(player.transform, Scientist.transform, angle))
    11.         {
    12.             Scientist.SetActive(false);
    13.         }
    14.     }
    15.  
    16.     private bool LookingAt(Transform looker, Transform target, float angleLimit)
    17.     {
    18.         //find rotation that looks directly at target
    19.         var targetLook = Quaternion.LookRotation(target.position - looker.position, looker.up);
    20.  
    21.         // even if clamped in the inspector, this ensures no shenanigans if the value was changed by code
    22.         angleLimit = Mathf.PingPong(angleLimit,180);  
    23.  
    24.         // calc target Dot product threshold from provided angle
    25.         var dot          = Mathf.Acos(angleLimit * Mathf.Deg2Rad);
    26.  
    27.         return Quaternion.Dot(looker.rotation,targetLook)>=dot;
    28.     }
    29.  
     
    cristo likes this.
  5. cristo

    cristo

    Joined:
    Dec 31, 2013
    Posts:
    265
    Thanks for taking the time to give me some help and more education.