Using AddRelativeForce in OnCollisionExit

So this is my first time posting in a forum so do excuse me for breaking any forum’s ethics.
Currently I have a school assigment, and I am developing pinball. As for the physics of the ball, I was giving it a Vector3.up, after hitting the flipper by using the OnTriggerEnter. However I found that it was not working as a pinball game should work, therefore I decided to change the ball’s physics by opting for the OnCollisionExit, and use the AddRelativeForce(Vector3.forward * 1000). However it seems that the relative force is only applied on the ball on the first hit. Obviously I want it to be applied each time. Below is the code:

function OnCollisionExit(otherCollision:Collision)
{
	if(otherCollision.gameObject.tag == "leftflipper" || otherCollision.gameObject.tag == "rightflipper")
	{
		j++;
		print(j);
		this.gameObject.rigidbody.AddRelativeForce(Vector3.forward * 1000);
	}
}

Thanks in advance for your help

The question would be, how are you moving your flipper?

Is your flipper being controlled by physics or by math.

The disclaimer would be that if you are using math (transform.Rotate or something similar) you are bypassing the physics updates. This would result in horrid results when trying to do a physics driven game. Pinball would fall into that category.

here is a trick.

On the flipper. First, make sure that you constrain it’s position. so it does not move. Next, freeze it’s X and Z rotation. (this really depends on how you set up your flipper) This will make sure that it doesnt turn in odd directions.

Now, you will need to build a custom “watcher” that makes sure that the flipper is maintained between two angles. This watcher will also watch the keys. So lets say that the left shift (KeyCode.LeftShift) and right shift (KeyCode.RightShift) control your flippers. In the FixedUpdate, you will see if either of those keys are active (Input.GetKey()) and apply torsion in the correct direction on the flipper. (since the other angles and the position is locked it wont move). To do this, simply add something like this:

		// force the angular velocity
		rigidbody.angularVelocity = transform.up * 100;

To Limit the angle, you will need to use a perfect euler angle. (I will post that later) You need to make sure that the angle that you are working with is between -180 and 180 degrees, clamp it, then set it back to that angle. The next part is that you will need to stop the angularVelocity when it reaches its limit.

		// make sure the euler we get is between -180 and 180
		euler = transform.localEulerAngles;
		euler.y = euler.y > 180 ? euler.y - 360 : euler.y;
		
		// clamp your angles so that you dont overshoot.
		euler.y = maxAngle > 0 ? Mathf.Clamp(euler.y, 0, maxAngle) : Mathf.Clamp(euler.y, maxAngle, 0);
		
		// if we hit the max angle, stop the velocity change.
		if(euler.y == maxAngle) rigidbody.angularVelocity = Vector3.zero;
		
		// set the euler back to the transform
		transform.localEulerAngles = euler;

So in this case, I am checking to see if the angle has reached maxAngle. If so, I simply set the angularVelocity back to Zero.

Now, the deal with “perfect” euler angles is that you need to get the localEulerAngles from your object. This gets angular values from the difference from it, to it’s parent. If you don’t have a parent, it gets it from the difference to the global world. This is usually bad. Any time you get a “difference” it will tend to mess up an EulerAngle badly. To fix this you “cheat”. Simply add a parent object to your flipper, that is in the same place and has the same rotation. When you get the euler, it will then give you numbers offset from it’s original rotation. This is good.

So your start will look something like this:

function Start(){
	// make sure we have a rigidbody
	if(!rigidbody)gameObject.AddComponent(Rigidbody);
	rigidbody.mass = mass;
	rigidbody.useGravity = false;
	
	// lock the rigidbody in place
	rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ | RigidbodyConstraints.FreezePosition;
	
	// hold the object so that you can get proper angles
	var obj:Transform = new GameObject("dummy holder").transform;
	obj.parent = transform.parent;
	obj.position = transform.position;
	obj.rotation = transform.rotation;
	transform.parent = obj.transform;
}

Notice, that I also gave the locks, and stopped gravity from affecting the flipper. I also put mass in.

OK, yes, I wrote the whole thing, (mostly cos I wanted to check for dumb errors) It should work just fine (but I didnt test it) See what you can come up with from that, and post your script back. If you run into big problems, just ask.

The point of the code I provided was to give a limiter. If you do what you have asked in this, you will ignore the limiter when you are above the euler angle. There is not stopping it, unless you set the angular velocity back to zero. Even then you will have to content with the angle being greater or less than the angle you want.