The question is answered, right answer was accepted
Physics object bouncing on collision.
I have seen this question asked multiple times but I have not found a solid solution.
My game involves fast moving objects and switching gravity. I have a big issue with objects 'bouncing' or colliding and clipping slightly then getting pushed back out.
Are there any good solutions to fix this, I have tried the script http://wiki.unity3d.com/index.php?title=DontGoThroughThings
But it has weird interactions with my character controller and does not work.
The bouncing affects my gameplay majorly as the player sometimes bounces and causes them to lose and it also looks bad when the objects clip.
Any solutions?
Code:
public gravityState state;
Collider boxCollider;
Rigidbody rb;
public float moveSpeed = 5f;
public GameObject destroyedCube;
public bool shouldMove = false;
public enum gravityState{
up,
down
}
protected virtual void OnEnable()
{
// Hook into the OnFingerTap event
Lean.LeanTouch.OnFingerTap += OnFingerTap;
}
protected virtual void OnDisable()
{
// Unhook into the OnFingerTap event
Lean.LeanTouch.OnFingerTap -= OnFingerTap;
}
// Use this for initialization
void Start () {
Physics.gravity = new Vector3(0,-75,0);
state = gravityState.down;
boxCollider = GetComponent<Collider>();
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update () {
//if(Input.GetMouseButtonDown(0) && canChange() && shouldStart && !Lean.LeanTouch.Fingers[0].IsOverGui =){
//SwitchGravity();
//}
}
void FixedUpdate(){
collisionForwardCheck();
if(shouldMove){
rb.MovePosition(transform.position + new Vector3(moveSpeed,0,0));
}
}
//Switches the physics gravity to the opposite
/// <summary>
/// Switchs the gravity.
/// </summary>
public void SwitchGravity(){
if(!Level.isPaused){
//Check current gravitystate and re-assign
if(state == gravityState.up){
state = gravityState.down;
}else{
state = gravityState.up;
}
//Invert physics
Physics.gravity = -Physics.gravity;
//Add to statistics
PlayerPrefs.SetFloat("switches", PlayerPrefs.GetFloat("switches") + 1);
}
}
/// <summary>
/// Cans the change.
/// </summary>
/// <returns><c>true</c>, if change was caned, <c>false</c> otherwise.</returns>
public bool canChange(){
if( Physics.Raycast(transform.position, -Vector3.up, boxCollider.bounds.extents.y + 0.3f)){
return true;
}else if(Physics.Raycast(transform.position, Vector3.up, boxCollider.bounds.extents.y + 0.3f)){
return true;
}else{
return false;
}
}
public void collisionForwardCheck(){
RaycastHit hit;
Ray ray = new Ray(transform.position, new Vector3(1,0,0));
Ray ray2 = new Ray(new Vector3(transform.position.x,transform.position.y + GetComponent<Collider>().bounds.extents.y), new Vector3(1,0,0));
Ray ray3 = new Ray(new Vector3(transform.position.x,transform.position.y - GetComponent<Collider>().bounds.extents.y), new Vector3(1,0,0));
if(Physics.Raycast(ray,out hit, GetComponent<Collider>().bounds.extents.x + 0.2f) || Physics.Raycast(ray2,out hit, GetComponent<Collider>().bounds.extents.x + 0.2f) || Physics.Raycast(ray3,out hit, GetComponent<Collider>().bounds.extents.x + 0.2f)){
if(hit.collider.tag == "Obstacle"){
if(state == gravityState.up){
SwitchGravity();
}
GameObject go = Instantiate(destroyedCube, transform.position,Quaternion.identity) as GameObject;
for(int i = 0; i<go.transform.childCount;i++){
if(go.tag == "broken")
go.transform.GetChild(i).GetComponent<Rigidbody>().velocity = rb.velocity * 10;
}
gameObject.SetActive(false);
}
}
}
I have added the code to the post, but what other info would you like?
$$anonymous$$ixing a Character Controller and a Rigidbody are generally not recommended on the same object. They generally mess with each other.
Your collisionForwardCheck()
looks expensive. I dont get why you use GetComponent<Collider>()
when youve declared boxCollider = GetComponent<Collider>();
in Start(). Just use boxCollider
.
Spam$$anonymous$$g out the Raycasts is expensive too. At a glance, your code looks like a manual Boxcast.
They may not make too much difference but as you are playing with Gravity and modifying velocities, in conjunction with $$anonymous$$ovePosition, the chances seem quite high of some Physics conflict. If your framerate drops a lot at any point the effects may be multiplied.
Note that CC has its own collision function
https://docs.unity3d.com/ScriptReference/CharacterController.OnControllerColliderHit.html
It is recommended to reduce as much of the load on FixedUpdate as you can. The smaller it is the better physics will behave and look.
Hey, just so you know, I am not using a character controller, but I completely understand the problem with raycasting and I was actually looking at using boxcasts. But in regards to the physics and applying velocity, I am only ever moving the rigidbody here
'rb.$$anonymous$$ovePosition(transform.position + new Vector3(moveSpeed,0,0));'
Thanks for helping, but you still haven't solved my original question of the collider clipping into the ground
$$anonymous$$ovePosition is retrospective, I guess. Its like PseudoPhysics. Its basically using translate with a sweeptest in between. If one object ends up within another object it will get pushed out, and I believe $$anonymous$$ovePosition moves first and tests after (I could be wrong).
Anyway, you did say
"But it has weird interactions with my character controller and does not work." :D