- Home /
Simple Collision Deflection (Pong)
Hi,
I am working on my first Unity game, a Pong clone.
I have utilised some of the in built features to get the main game working although I am having trouble with the ball deflecting at an angle off the paddle unless it hits the edge. When it hits the flat face of the object it just deflects horizontally across the x plane.
The ball is a rigidbody which hits box colliders on the paddles. The ball has one script and the verticalcontroller script manages the paddles.
Also there is no gravity, angular drag or friction enabled.
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
private const float velocityIncrement = 1.0f;
void Start() {
Reset();
}
void OnTriggerEnter(){
Reset();
}
void Update()
{
//rigidbody.AddForce(10, 10, 0, ForceMode.Impulse);
rigidbody.velocity *= velocityIncrement;
}
private void Reset()
{
transform.position = Vector3.zero;
rigidbody.velocity = new Vector3 (80,1,0);
//rigidbody.angularVelocity = new Vector3 (0,10,0);
}
}
using UnityEngine;
using System.Collections;
public class VerticalController : MonoBehaviour {
public string axisName = "Vertical";
public float speed = .5f;
// Update is called once per frame
void Update () {
var delta = new Vector3(0,speed,0);
if (Input.GetAxis(axisName) >= .001)
delta *= 1f;
else if (Input.GetAxis(axisName) <= -.001)
delta *= -1f;
else
delta = Vector3.zero;
transform.position += delta;
}
}
Answer by Tyler 10 · Jan 19, 2012 at 05:48 PM
You should check out these functions:
http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.OnCollisionEnter.html http://unity3d.com/support/documentation/ScriptReference/Collider.OnCollisionExit.html
Once you know your ball has collided with your paddle, you can add a force based on the balls distance to the center of the paddle. That way, if its above the center of the paddle it will make the ball go up, and if its below, it will make the ball go down.
It would look something like this
function OnCollisionEnter(collision : Collision) { var ball:Rigidbody = collision.rigidbody; if(ball.transform.y > transform.y){ ball.addforce(. . . . .) . . . . } }
Thanks for replying Tyler, I appreciate it.
I tried using your code but it threw errors. It took me a while to realise that it was JavaScript and my code is written in C#
I started to try and convert the code but I keep running into more and more errors. Would you or anyone else be able to fix this?
void OnCollisionEnter(Collision collision){
if (collision.gameObject.name == "Ball"){
//Ball.Rigidbody = collision.rigidbody;
if(Ball.transform.y > transform.y){
Ball.AddForce(1.0f);
}else
if(Ball.transform.y < transform.y){
Ball.AddForce(-1.0f);
}
}
}
The current errors are CS0120 and CS0117 (Ball does not contain a definition for Rigidbody and an object is required to access non static member transform
It looks like you are trying to access the transform on your Ball class, rather than the property on your ball object. From what I see you would need to first get the ball object like this:
if (collision.gameObject.name == "Ball"){ GameObject aBall = collision.gameObject; if(aBall.transform.y > transform.y){// do stuff}
Ok it seems to understand the ball bit now but still no luck with the if clauses. I've commented the code to help you understand what I'm trying to do. $$anonymous$$y full vertical controller script is in the original post and I was thinking maybe I would need to pull some values from it somehow for the paddle position to then get the location on the paddle? I'm finding this really confusing, sorry.
//upon collision void OnCollisionEnter(Collision collision){
//if the collision involves the game object Ball
if(collision.gameObject.name == "Ball"){
//assign collision details to aBall
GameObject aBall = collision.gameObject;
//assign leftpaddle and rightpaddle vars
GameObject lpaddle = gameObject.name == "LeftPaddle";
GameObject rpaddle = gameObject.name == "RightPaddle";
/*if the collision position is on the upper half of prefab "paddle" aka game objects "LeftPaddle" and "RightPaddle" then add a small angled upwards force else if it is on the lower half of the paddle object add a small angled downwards force*/
if(aBall.position > lpaddle.ContactPoint(Vector3(0,0,0)){
aBall.AddForce(1,1,0);
}else
if(aBall.transform.position < transform.position){
aBall.AddForce(-1,-1,0);
}
} }
Yeah, you are getting close. I wouldn't use the contact point since that is a local point (i believe). You can just say:
if(aBall.transform.position.y - lpaddle.transform.position.y > 0){ aBall.AddForce(0,10,0); }
Adding a force of 1 will probably not do anything noticeable.
Also, I am assu$$anonymous$$g your anchor point on your paddle is in the middle of the paddle, and your game is being played in the xy plane. If your game is in the xz plane you would need to compare the balls and paddles transform.position.z. Try debugging the point to see if you are getting close like:
Debug.Log("Local contact points: " + aBall.position.y - lpaddle.transform.position.y);
I haven't set a custom anchor point and the gizmo is still located on the centre of the paddle so I assume the anchor point is in the middle. The game is being played along the XY plane. I can't use the debug line because Unity is throwing errors at the paddle gameobjects before it
GameObject lpaddle = gameObject.name == "LeftPaddle"; GameObject rpaddle = gameObject.name == "RightPaddle";
error CS0029: Cannot implicitly convert type bool' to
UnityEngine.GameObject'
It also doesn't seem to recognise the force element
aBall.AddForce(0,10,0);
error CS1061: Type UnityEngine.GameObject' does not contain a definition for
AddForce' and no extension method AddForce' of type
UnityEngine.GameObject' could be found (are you missing a using directive or an assembly reference?)
Your answer
Follow this Question
Related Questions
Ball jump on collision problem 1 Answer
Scoring not working 2 Answers
Moving a ball around a maze 3 Answers
What is the best way to move a paddle accurately in a circle? 2 Answers