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:
- Adding detailed logging to ensure that the
OnTrigger
functions were being called correctly. - Increasing the size of the platform's trigger collider.
- Disabling
SetParent
temporarily to confirm if parenting was the issue. - Moving input handling to Update and physics updates to
FixedUpdate
. - 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;
}
}
}
Transform.rotation
instead ofRigidbody.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 itsTransform
rather than itsRigidbody
. \$\endgroup\$