- Home /
Rigidbody movement along a Circular Path.
Hello, I am in need of some assistance with my code and am hoping somebody can help.
I am looking to create a game in which a ball move along a circular path as shown in this video http://youtu.be/m9hzwftZGYM, however require the ball to move realistically.
I have created 2 scripts that move the ball so far, the first of which moves the rigidbody using addforce however, it only moves along one axis (no rotation).
The second script rotates the ball round an origin point however does not roll.
I need to combine the two scripts so the ball acts realistically as it rotates around the centre point.
Script 1
using UnityEngine; using System.Collections;
public class PlayerController : MonoBehaviour {
public float speed;
public float jumpHeight;
public Transform centre;
bool IsFalling = false;
void FixedUpdate()
{
//Ball Movement
float moveHorizontal = Input.GetAxis ("Horizontal");
Vector3 movement = new Vector3 (moveHorizontal, 0, 0);
rigidbody.AddForce (movement * speed * Time.deltaTime);
//Ball Jump
if (Input.GetKeyDown (KeyCode.W) && IsFalling == false)
{
rigidbody.velocity += Vector3.up * jumpHeight;
IsFalling = true;
}
}
void OnCollisionStay()
{
IsFalling = false;
}
}
Script 2
using UnityEngine;
using System.Collections;
public class PlayerController2 : MonoBehaviour
{
Quaternion rotation;
public Transform centre;
public Vector3 playerRadius = new Vector3(0, 0.5f, -5);
float currentRotation = 0.0f;
void Update ()
{
currentRotation += Input.GetAxis("Horizontal")*Time.deltaTime*100;
rotation.eulerAngles = new Vector3(0, currentRotation, 0);
transform.position = rotation * playerRadius;
Vector3 worldLookDirection = centre.position - transform.position;
Vector3 localLookDirection = transform.InverseTransformDirection(worldLookDirection);
localLookDirection.y = 0;
transform.forward = transform.rotation * localLookDirection;
transform.eulerAngles = new Vector3(0, currentRotation, 0);
}
}
Thankyou.
Answer by NoseKills · Jul 07, 2014 at 02:58 PM
Should work if you force the direction of the ball's speed to be perpendicular to a vector coming from the center of the Tower in the update method.
I was able to get this result:
Video (at one point I'm changing the radius on the fly in case you wonder what's happening)
With this code:
using UnityEngine;
using System.Collections;
public class Vects : MonoBehaviour
{
public float _StartAltitude;
public float _Radius;
public Rigidbody _Ball;
public Transform _Cylinder;
// Use this for initialization
void Start ()
{
_Cylinder.position = Vector.zero;
_Ball.transform.position = new Vector3(_Radius, _StartAltitude, 0f);
_Ball.AddForce(Vector3.forward * 200);
}
void Update()
{
Vector3 v = _Ball.velocity;
// any vecotr from cylinders up axis to ball pos
Vector3 radius = _Ball.transform.position - _Cylinder.transform.position;
if (v.x == 0 && v.z == 0)
{
// ball only bouncing up & down. Can't calculate tangetial speed
}
else
{
// a vector perpendicular to both of those
// (a vector that would be an acceptable velocity for the ball sans the vertical component)
Vector3 tangent = Vector3.Cross(Vector3.up, radius);
// store the magnitude so we don't lose momentum when changing direction of speed
float mag = _Ball.velocity.magnitude;
// new speed is the old velocity projected on a plane defined by "up" and "tangent"
Vector3 newVelo = (Vector3.Project(v, tangent) + Vector3.Project(v, Vector3.up)).normalized * mag;
_Ball.rigidbody.velocity = newVelo;
}
// set the ball to the correct distance from the cylinder axis (assuming the vertical axis of cylinder is at X==0 && Z==0)
radius.y = 0;
radius = radius.normalized * _Radius;
radius.y = _Ball.transform.position.y;
_Ball.transform.position = radius;
}
}
If i were to do a game like that though, I'm not sure if I'd make the ball move. Might be easier to just make the 'tower' rotate under it.
Thankyou for the quick reply, i hope it will work. Would moving the rest of the game world (even after adding in collectables/moving platforms) really be easier?
Edited answer. Seems to work pretty well.
The more I look at the video the more convinced I am that either the ball doesn't have "real" physics, and/or that it's the tower that's rotating under it.
The ball doesn't have any momentum. It "stops on a dime" and it can even land on a platform only partially and still stay there. With the free ball movement approach you have to specifically modify the original velocity of the ball to make it stop when the key is released.
Also the platforms and other level design should be pretty easy to do if you parent the platforms to the tower and move / animate them in local coordinate space. Then just rotate the tower and the obstacles follow the rotation automagically, so it shouldn't make it any harder than having a stationary tower.
$$anonymous$$y answer should still cover the original question, so please mark it as an answer if it helped :)
Thank You again for your help already.
I have implemented the code you have given me and have some promising results. However, whilst the ball moves in a circle it does not rotate therefore will not rotate around the centre point fully. Shown here in this video http://youtu.be/mREfLPRRGz4 (in the video I press to move left, the reset, then press to move right)
Do I need to make the z axis of the ball always point to the centre somehow?
It might work if you set
_Ball.transform.LookAt(new Vector3(_Cylinder.position.x, _Ball.transform.position.y, _Cylinder.position.z));
in Start() and Update()
If that still messes up the continuity of the rotation, i'll need to check the math for the rotation when i get home.
When I place in this code, the ball now faces the correct way, however it no longer rolls and still only moves 180 maximum (Before http://youtu.be/dxJfN0T4FLU, After http://youtu.be/1JlnvTQvsb4)
I have played around with the code a lot today but haven't got anywhere.
Here is my current PlayerController class
void Start()
{
//centre.position = Vector3.zero;
transform.position = new Vector3 (0, startPositionY, startPositionZ);
rigidbody.transform.LookAt (new Vector3(centre.position.x, rigidbody.position.y, centre.position.z));
}
void FixedUpdate()
{
//Ball $$anonymous$$ovement
float moveHorizontal = Input.GetAxis ("Horizontal");
Vector3 movement = new Vector3 (moveHorizontal, 0, 0);
rigidbody.AddForce (movement * speed * Time.deltaTime);
Vector3 velocity = rigidbody.velocity;
Vector3 radius = rigidbody.transform.position - centre.transform.position;
//radius.y = 0;
radius = radius.normalized * _radius;
//radius.y = rigidbody.transform.position.y;
//Ball Position on Plane (Degrees)
currentAnglePosition = -(($$anonymous$$athf.Atan2(rigidbody.position.z , rigidbody.position.x) * (180 / $$anonymous$$athf.PI)) - 90);
rigidbody.$$anonymous$$ovePosition (radius);
rigidbody.transform.LookAt (new Vector3(centre.position.x, rigidbody.position.y, centre.position.z));
//Ball Jump
if (Input.Get$$anonymous$$eyDown ($$anonymous$$eyCode.W) && IsFalling == false)
{
rigidbody.velocity += Vector3.up * jumpHeight;
IsFalling = true;
}
}
void OnCollisionStay()
{
IsFalling = false;
}
}
Your answer
Follow this Question
Related Questions
Flip over an object (smooth transition) 3 Answers
Making a bubble level (not a game but work tool) 1 Answer
GetButtonDown is unresponsive 0 Answers