I have set up box colliders for my 2D game. It works great when the Player (Character Controller) is moving around using the joystick. However, I have enemies that I want to push the Player when they hit him. The problem is the Enemy can push the Player outside of the boundaries. Once outside, the Player can’t get back in!
Here’s the Enemy code that I’m using to push the player on colliding:
IEnumerator Hit()
{
if( hit )
{
player.transform.Translate( 0, 0, -hitDistance * Time.deltaTime);
print("you hit me...");
yield return new WaitForSeconds( hitTime );
}
}
I’ve tried adding a Rigidbody (kinematic) to both the Player and the Boundary walls and while it sometimes works if I set the collision mode to Continuous, it is not reliable. I’ve seen posts suggesting to use the Mathf.Clamp function, but since I’m using a Character Controller and not simply moving the Player using math I don’t think that would work. I also would like to avoid a complex check on all four boundaries (left, right, top, bottom) since this is for iOS and I want it to perform as fast as possible on older iOS devices.
Any suggestions on a reliable, fool-proof boundary system that will keep my Player in bounds, even if he is being pushed around by the Enemy characters?
You are moving the player using math:
player.transform.Translate( 0, 0, -hitDistance * Time.deltaTime);
So yes, Clamp will work. It would work even if you were using 100% physics.
–Eric
You are moving the player using math:
player.transform.Translate( 0, 0, -hitDistance * Time.deltaTime);
So yes, Clamp will work. It would work even if you were using 100% physics.
–Eric
Thanks! Hmm… so I am using Math after all. I’ve altered the C# code based on this answer and it works like a charm!
IEnumerator Hit()
{
if( hit )
{
Vector3 pos = player.transform.position;
player.transform.Translate( 0, 0, -hitDistance * Time.deltaTime);
pos.x = Mathf.Clamp(player.transform.position.x, -8F, 8F);
pos.z = Mathf.Clamp(player.transform.position.z, -17F, 80F);
player.transform.position = pos;
yield return new WaitForSeconds( hitTime );
}
}
I went ahead and added a Kinematic Rigid body to the Enemy, but did not need to add anything to the Player or the boundaries. The performance on iOS seems fine.
BTW, this is for a top-down 2D game, so I’m only needing to restrict the x, z boundaries.
The Hit code above mostly works, but my Player controller script would still allow the player to turn, and if they also accelerated they could still go out of bounds. So, instead of checking for bounds from the Enemy, I’ve added the following code to my Player Controller script in the Update loop:
pos = thisTransform.transform.position; //after we apply all of the Inputs (joystick, tilt, etc.) we store the current position
character.Move( movement ); //move the character already!
pos.x = Mathf.Clamp(thisTransform.position.x, -8F, 8F); //let's clamp the x position for out of bounds
pos.z = Mathf.Clamp(thisTransform.position.z, -17F, 80F); //let's also clamp the Z out of bounds coordinates
thisTransform.position = pos; //the player must never go out of bounds!
Now, I don’t even need boundary collider objects, so we just keep the player in bounds using Mathf.Clamp.
Hope this helps others, I’m sure there are even more efficient ways to deal with boundaries, but this works for me.