- Home /
Object Leaves Parent's Trigger During Parent Movement
Scenario:
1 Platform GameObject (contains 2 Box colliders - 1 trigger/other not)
1 Cube GabeObject (contains box collider and player controller)
The platform moves up and down
The cube rides the platform
The cube has a script that applies gravity and allows the cube to jump. The cube has Trigger events that handle parenting the platform. (See code below)
Expected Result:
Cube lands on platform
Cube becomes child to platform
Cube moves with platform
Cube jumps
Cube no longer child to platform
Cube falls
Repeat
Problem:
The issue occurs when the platform moves downward. This causes a TriggerExit()
to be thrown and the cube receives this before moving with the platform. This causes a bouncing issue while the platform moves down.
CODE:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BoxGravity : MonoBehaviour {
public float jumpForce = 20f;
public float gravityScale = 10f;
private CharacterController controller;
private Vector3 moveDirection;
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Platform")
{
transform.parent = other.transform;
}
}
void OnTriggerStay(Collider other){/*Same as enter*/}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Platform")
{
transform.parent = null;
}
}
void Start () {
controller = GetComponent<CharacterController>();
moveDirection = new Vector3(0, 0, 0);
}
void Update () {
if(controller.isGrounded)
{
moveDirection.y = 0;
if (Input.GetButtonDown("Jump"))
{
moveDirection.y = jumpForce;
}
}
moveDirection.y = moveDirection.y + (Physics.gravity.y * gravityScale * Time.deltaTime);
controller.Move(moveDirection*Time.deltaTime);
}
}
Sample image:
Question:
How can I prevent the TriggerExit()
from getting called before the child moves with its parent?
If not possible, how can I prevent this bouncing issue?
Answer by TSI25 · Oct 26, 2017 at 02:27 PM
I've seen a problem like this before, when colliders are moved they actually get recalculated and that can fire an ontriggerexit. I forget how I got around it, and I can never find anything in the manual about it I had to hear about it at Unite 2016 in an optimizations talk XD.
you could try using a downward raycast from the player to detect a platform. if its within x distance reparent it and if not then parent to nothing, but youd need to be raycasting pretty much constantly is the problem there.
I suppose you could do a mash of both, like on trigger enter and on trigger exit fire that raycast and if theres a platform parent or stay parented, and if not then parent to nothing (just to avoid constantly casting.)
I have tried raycasting, but this just comes with too many issues. Its costly to raycast, especially if done constantly. This also causes landing and jumping issues. If the raycast is too short, then the issue doesn't get fixed and more resources get spent, if its too long then jumping becomes too complicated and normally does not work. This can also cause landing problems and creates a landing that is not smooth.
I'm looking for some way I can prevent an improper call to OnTriggerExit()
or some kind of check or flag to deter$$anonymous$$e if an improper call was made.
well you cant prevent the engine from calling those triggers unless you roll your own collider system, because those calls and their functionality are packed into unity. I suppose you could get the colliders and manually check if they are intersecting in OnTriggerExit to see if they havent REALLY stopped intersecting with a call like this but I'm very skeptical that that will be cheaper than a raycast. $$anonymous$$y general understanding of raycasting is that most of the time its quite cheap unless you're casting all the time, or making use of Physics.RaycastAll
Okay, well that answers "How can I prevent the OnTriggerExit()
from getting called before the child moves with its parent? " I managed to figure out a way to deter$$anonymous$$e a false OnTriggerExit()
throw using bools. (Answer below).
Answer by uulamock_unity · Oct 26, 2017 at 04:03 PM
One fix I came across is to have bools keep track of if the cube is doing any kind of movement action. In the example above, it would be as simple as this:
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Platform")
{
if(isJumping)
transform.parent = null;
}
}
This is a pseudo way of determining a false OnTriggerExit()
throw. However, this can become complicated real fast. What if a new outside source moves the cube off the platform? Like a gust of wind or another cube? Now you have another bool. And then new things could happen, thus more checks. etc.
My idea is to check for 2 bools.
private bool isMoving, isPushed;
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Platform")
{
if(isMoving || isPushed)
transform.parent = null;
}
}
isMoving
andisPushed
is set tofalse
every UpdateWhenever player input moves cube, set
isMoving = true;
Whenever an outside source moves cube, set
isPushed = true;
This answers the "If not possible, how can I prevent this bouncing issue?" but not how to prevent a false OnTriggerExit()
from being thrown.
NOTE: This can still have issues. if you are moving while the false OnTriggerExit()
is thrown, the issue will still occur.
Your answer
Follow this Question
Related Questions
How to move while jumping? 1 Answer
Multiple Cars not working 1 Answer
How do I solve this error? 2 Answers
How to Make A 'Punch' Remove Health 2 Answers