- Home /
Simulating the graphics of a rolling 3D ball in a 2D game
Hello everyone.
I'm creating a Pong-like game in Unity 4.6.1, and I'd like the ball to look more "alive" than a static sprite. I'd like for it to look like it's rolling, in the direction of the velocity of its Rigidbody2D, and maybe even with some spin on it.
I'm not necessarily looking for a complete solution. Just suggestions as to how I can achieve this effect. I've thought up two suggestions myself, but think these might be stupid or painful to achieve:
1) Create the sprite with a Collider2D, disable the sprite renderer, and add a child sphere to it with the same width as the sprite's Collider2D (with some texture to see how it is rotating). Then I'd manually add torque to the sphere, depending on the velocity of the 2D rigidbody. I'm afraid, that decoupling the sphere from the physics, might make it look unrealistic. I've tried the following, but it does not even remotely give the desired effect (it seems to just spin randomly):
// Changing the 3D rigidbody of the sphere, using the velocities of
// the rigidbody2D of the sprite
Sphere.rigidbody.AddTorque(rigidbody2D.velocity.x, rigidbody2D.velocity.y, 0, ForceMode.VelocityChange);
Using this instead, I can get it to look like it is rolling correctly, but only when the ball is rolling horizontally. When the ball starts rolling laterally, it looks weird, until it returns to a horizontal movement again. It also rotates way too slow compared to what it should, and multiplying the value doesn't do anything.
Sphere.rigidbody.AddTorque(0, -rigidbody2D.velocity.x, 0, ForceMode.VelocityChange);
2) Somehow use a shader on the sprite to achieve the effect (no idea how, as I'm supern00b at shaders).
Any other suggestions? Thanks in advance for your comments.
Sincerely, Ultroman
Answer by Scribe · Jan 19, 2015 at 06:27 PM
For the first method you need to calculate the axis around which to rotate, so in this setup I had a gameObject (A) with a rigidbody and 2D circle collider, and a 3D sphere object (B) as a child of A with nothing except its transform and mesh renderer components.
The the following (C#) code should be added to object A, this code assumes you are looking along the z-axis, if you are looking along a different axis you will need to change the second argument of the cross product to match (and possibly multiply the angle by -1):
public Transform sphere3D;
public float ballRadius = 1;
float c;
Rigidbody2D rb;
Vector3 axis;
float angle;
void Start () {
c = 2*Mathf.PI*ballRadius;
rb = rigidbody2D;
}
void Update () {
axis = Vector3.Cross(rb.velocity, Vector3.forward);
angle = (rb.velocity.magnitude*360/c);
sphere3D.Rotate(axis, angle*Time.deltaTime, Space.World);
}
you should set the 'sphere3D' transform to object B, and set the radius if it is not the standard sphere scaling.
Then as your object A moves, the child will rotate but not effect anything else.
For the second option you suggested, you could just have a flat texture that you move the offset in the minus direction of your velocity, I think the water shader in standard assets uses offset changes to simulate water flow, so you could check that for how to pull this effect off if I have remembered correctly!
Scribe
Wow, thanks! That's brilliant! I'll be going with the first option. Thank you very much :D
Answer by Tepei · Jan 19, 2015 at 05:50 PM
Difficult to understand what you want whithout visual..
Maybe if the uv of your balls are set in the good direction, you juste have to ofset the texture to adjust the speed of the rotation.. So no need for a special shader..
Thanks for the suggestion. That was somewhat what I was thinking with my second suggestion. I'm gonna go with Scribe's solution with the sphere.