2
\$\begingroup\$

I'm developing a character controller in Unity and running into a problem with my character repeatedly entering and exiting a trigger collider on a moving platform. The character should stay within the trigger zone on the platform, but it constantly triggers OnTriggerEnter and OnTriggerExit events as if it's repeatedly re-entering the collider.

Here's the setup:

Platform: The platform has a Box Collider with Is Trigger enabled and a Rigidbody set to Is Kinematic.

Character: The character has a Rigidbody (with Interpolation set to Interpolate) and a Collider. It also uses a script for movement (PlayerInput), where movement is controlled by setting the Rigidbody.velocity.

Movement and Parenting Logic: When the character enters the platform's trigger, it should become a child of the platform to move along with it. This is done in OnTriggerEnter. When it exits the platform's trigger, it should be removed as a child in OnTriggerExit. Problem: When the character is on the platform, it constantly triggers OnTriggerEnter and OnTriggerExit every frame, even though it's not actually leaving the collider. This only happens when the platform is moving or rotating. I tried several solutions, including:

  1. Adding detailed logging to ensure that the OnTrigger functions were being called correctly.
  2. Increasing the size of the platform's trigger collider.
  3. Disabling SetParent temporarily to confirm if parenting was the issue.
  4. Moving input handling to Update and physics updates to FixedUpdate.
  5. Ensuring all Rigidbody components are set to Interpolate where necessary.

Despite these changes, the issue persists. It seems that the movement of the platform, especially rotation, might be causing the OnTrigger events to fire repeatedly.

Current code I'm using for the platform's trigger logic:

using UnityEngine;

public class MovePlatform : MonoBehaviour
{
    public string playerTag = "Player";
    public Transform platform;

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag(playerTag))
        {
            other.transform.SetParent(platform);
            Debug.Log("Enter trigger");
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.CompareTag(playerTag))
        {
            other.transform.SetParent(null);
            Debug.Log("Exit trigger");
        }
    }
}

and player:

using UnityEngine;

[RequireComponent(typeof(Rigidbody), typeof(Animator))]
public class PlayerInput : MonoBehaviour
{
    public float moveSpeed = 5f;            
    public float jumpForce = 5f;            
    public Transform cameraTransform;       
    public float rotationSpeed = 720f;      // character's rotation speed in degrees per second    
    public float rotationOffset = 0f;       // rotation offset for correction

    private Rigidbody rb;
    private Animator animator;
    private bool isGrounded = true;        

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        animator = GetComponent<Animator>();

        if (cameraTransform == null)
        {
            cameraTransform = Camera.main.transform; 
        }
    }

    void Update()
    {
        Move();     
        Jump();     
        UpdateAnimatorParameters(); 
    }

    private void Move()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");
        Vector3 cameraForward = cameraTransform.forward;
        Vector3 cameraRight = cameraTransform.right;

        cameraForward.y = 0;
        cameraRight.y = 0;
        cameraForward.Normalize();
        cameraRight.Normalize();

        Vector3 moveDirection = (cameraForward * moveVertical + cameraRight * moveHorizontal).normalized;
        Vector3 velocity = moveDirection * moveSpeed;
        rb.velocity = new Vector3(velocity.x, rb.velocity.y, velocity.z);

        if (moveDirection.magnitude > 0.1f) //оффсет для правильного отображения модели
        {
            Quaternion targetRotation = Quaternion.LookRotation(moveDirection) * Quaternion.Euler(0, rotationOffset, 0);
            transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
        }
    }

    private void Jump()
    {
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            isGrounded = false;
        }
    }

    private void UpdateAnimatorParameters()
    {
        bool isMoving = rb.velocity.magnitude > 0.1f;
        animator.SetBool("isRunning", isMoving);

        if (Input.GetKeyDown(KeyCode.F))
        {
            bool isDancing = animator.GetBool("isDancing");
            animator.SetBool("isDancing", !isDancing); 
        }
    }

    private void OnCollisionEnter(Collision collision) //реализация isground
    {
        if (collision.contacts[0].normal.y > 0.5f)
        {
            isGrounded = true;
        }
    }
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ You're changing rotation with Transform.rotation instead of Rigidbody.MoveRotation(). This rips the object out of the physics system and then puts it back in its new orientation, like a teleport, rather than rotating in-place. So that could cause the issue you're seeing. This can also happen if you're moving the platform with its Transform rather than its Rigidbody. \$\endgroup\$
    – DMGregory
    Commented Nov 14 at 13:23
  • \$\begingroup\$ @DMGregory Thank you, I will change it in future \$\endgroup\$
    – phdex
    Commented Nov 20 at 11:56

1 Answer 1

4
\$\begingroup\$

The issue is resolved! It turned out the problem was due to two colliders attached to the character that were conflicting with each other. Removing the extra collider fixed the constant trigger enter/exit problem on the moving platform. Hopefully, this helps anyone facing a similar issue!

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .