Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Solved] Effectors won't work while rotating

Discussion in 'Physics' started by Cybearg, Jul 3, 2016.

  1. Cybearg

    Cybearg

    Joined:
    Jan 18, 2015
    Posts:
    46
    I've got a player gameObject with a RigidBody2D on it, and childed is a PlayerBody gameObject that has all the various colliders for the player (this way parenting the camera or other things to the main Player game object won't cause issues when rotating, flipping the sprite, etc.).

    An important part of my game is the use of effectors such as AreaEffector2Ds and PointEffector2Ds. I've created a script to rotate the player so their feet always face the direction the AreaEffector is pushing toward or toward the effector's gameObject in the case of a PointEffector2D, see below. In case it helps, I've also included a peek at the player and the inspector below. In case you're wondering, the Hitbox gameObjects all have different triggers attached, but they're all on layers that are ignored by the Effector2Ds. Only the Player and Default layers are allowed to interact with the effectors.

    The problem? The player isn't drawn by the Effector2D's force while rotating! As soon as rotation is complete, the player is correctly drawn by forces with the right power/direction. What's going on?! I'd appreciate any help or insight that can be offered

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class EffectorRotation : MonoBehaviour {
    6.     public GameObject objectToRotate = null;
    7.     public new Rigidbody2D rigidbody = null;
    8.     public float rotateSpeed = 5f;
    9.  
    10.     private Quaternion defaultRotation;
    11.     private float defaultGravityScale;
    12.     private Effector2D currentEffector = null;
    13.     private Quaternion effectorRotation;
    14.     private bool updateRotationEachFrame = false;
    15.  
    16.     void Start() {
    17.         rigidbody.constraints = RigidbodyConstraints2D.FreezeRotation;
    18.         defaultRotation = Quaternion.FromToRotation(objectToRotate.transform.up, Vector2.up);
    19.         defaultGravityScale = rigidbody.gravityScale;
    20.     }
    21.  
    22.     void OnTriggerEnter2D(Collider2D col) {
    23.         SetEffectorFromCollider(col);
    24.     }
    25.  
    26.     void OnTriggerStay2D(Collider2D col) {
    27.         // if trigger didn't register correctly, treat it as a new triggering
    28.         if (currentEffector == null) {
    29.             SetEffectorFromCollider(col);
    30.         }
    31.     }
    32.  
    33.     void OnTriggerExit2D(Collider2D col) {
    34.         UnsetCurrentEffector();
    35.     }
    36.  
    37.     void FixedUpdate() {
    38.         if (currentEffector != null) {
    39.             if (updateRotationEachFrame)
    40.                 GetRotationFromEffector();
    41.  
    42.             RotateToward(effectorRotation);
    43.         } else {
    44.             RotateToward(defaultRotation);
    45.         }
    46.     }
    47.  
    48.     private void SetEffectorFromCollider(Collider2D col) {
    49.         currentEffector = col.GetComponent<Effector2D>();
    50.         if (currentEffector) { // if an effector is found
    51.             rigidbody.gravityScale = 0;
    52.             AreaEffector2D areaEffector = null;
    53.             updateRotationEachFrame = false;
    54.  
    55.             if ((areaEffector = currentEffector as AreaEffector2D) != null) {
    56.                 var forceAngle = Quaternion.identity;
    57.                 forceAngle.eulerAngles = new Vector3(0, 0, areaEffector.forceAngle + 90);
    58.  
    59.                 effectorRotation = areaEffector.transform.rotation * forceAngle;
    60.             } else if (currentEffector is PointEffector2D) {
    61.                 updateRotationEachFrame = true;
    62.             } else {
    63.                 UnsetCurrentEffector(); // don't rotate toward other types of effectors
    64.             }
    65.         }
    66.     }
    67.  
    68.     private void UnsetCurrentEffector() {
    69.         currentEffector = null;
    70.         rigidbody.gravityScale = defaultGravityScale;
    71.     }
    72.  
    73.     private void GetRotationFromEffector() {
    74.         var gravityUp = (objectToRotate.transform.position - currentEffector.transform.position).normalized;
    75.         var localUp = objectToRotate.transform.up;
    76.  
    77.         effectorRotation = Quaternion.FromToRotation(localUp, gravityUp) * objectToRotate.transform.rotation;
    78.     }
    79.  
    80.     private void RotateToward(Quaternion target) {
    81.         objectToRotate.transform.rotation = Quaternion.Slerp(objectToRotate.transform.rotation, target, rotateSpeed * Time.deltaTime);
    82.     }
    83. }
    84.  
    playerHierarchy.png
     
  2. Cybearg

    Cybearg

    Joined:
    Jan 18, 2015
    Posts:
    46
    It seems that the problem was simply that the TestPlayer had a z position of -1. Setting its z to 0 (which happens to be the same z as the object with the Effector2Ds) seemed to fix the issue! There may have also been an issue with the player's colliders and rigidbody2d being on different gameObjects, but the z-position could well have been the root of all other issues. I changed both things and it's better, so I know for sure that the -1 z played a part.