- Home /
adding a force to a dice and find out which face collided with the ground
I'm having trouble adding strength to a dice and make him go forward and then after a certain time. And also like to know what was the face that is glued to the floor in order to then pin down the value of the dice.
Sorry for the question. Because I am a beginner in programming. Sorry for my bad English.
using UnityEngine; using System.Collections;
public class Dice1Script : MonoBehaviour {
public CubePlayerScript cubePlayerScript;
public float forceMove = 5.0f;
public GameObject face1;
public GameObject face2;
public GameObject face3;
public GameObject face4;
public GameObject face5;
public GameObject face6;
// Update is called once per frame
void Update () {
if (cubePlayerScript.launchedDice) {
rigidbody.AddForce(forceMove * Time.deltaTime, 0, 0);
}
if (rigidbody.velocity == Vector3.zero) {
if(Physics.Linecast(transform.position, face1.transform.position)){
Debug.Log("The dice value is 6");
}
}
}
}
Answer by robertbu · Sep 25, 2014 at 12:14 PM
Typically you are rolling dice, you want to add force once, not every frame, and if you are adding force over multiple frames, then it should be done in FixedUpdate(), not Update. I don't see where cubePlayerScript.launchDice gets set, so I'm not sure how you are handling force.
Assuming you left the mass at 1.0, the amount of force you are applying is too small. Depending on your scale, typical values are for AddForce for a mass of 1.0 are in the 500 to 2000 range. Assuming 60 fps, your force is 5/60 = .083.
You likely want to do both an AddForce() and an AddTorque() so the dice both spins and moves.
As for telling which side is up, you can use Vector3.Dot() or Vector3.Angle(). If I calculate these six values:
Vector3.Dot(transform.up, Vector3.up);
Vector3.Dot(transform.right, Vector3.up);
Vector3.Dot(transform.forward, Vector3.up);
Vector3.Dot(-transform.up, Vector3.up);
Vector3.Dot(-transform.right, Vector3.up);
Vector3.Dot(-transform.forward, Vector3.up);
The highest one will be the side that is most upfacing. If the dice are on a flat surface, the value will be near or at 1.0 for the side facing up. Note the side facing down will have a value of near or at -1.0.
Here is a script to get you started. The values on the sides of the dice are based on the texture at this link:
http://answers.unity3d.com/questions/458491/how-to-map-texture-in-a-cube.html
...with 1 being up and 3 being forward.
using UnityEngine;
using System.Collections;
public class Dice : $$anonymous$$onoBehaviour {
Vector3[] faces = {Vector3.up, Vector3.right, Vector3.forward, -Vector3.forward, -Vector3.right, -Vector3.up};
bool rolling = false;
void Update () {
if (rolling && rigidbody.velocity.magnitude < 0.001f) {
rolling = false;
int i = WhichSide();
if (i == -1) {
Debug.Log ("At an angle");
}
else {
Debug.Log ("Displaying value " + i);
}
}
if (Input.Get$$anonymous$$eyDown ($$anonymous$$eyCode.Space)) {
RollDice();
}
}
void RollDice () {
rolling = true;
Vector3 force = Vector3.forward * Random.Range (400.0f, 600.0f) + Vector3.up * Random.Range (200.0f, 250.0f) + Vector3.right * Random.Range(-50.0f, 50.0f);
rigidbody.AddForce (force);
Vector3 v = Vector3.forward;
v = Random.rotation * v;
rigidbody.AddTorque (v * 25.0f);
}
int WhichSide() {
for (int i = 0; i < faces.Length; i++) {
if (Vector3.Dot(Vector3.up, transform.TransformDirection(faces[i])) > 0.8f) {
return i+1;
}
}
return -1;
}
}
Answer by sevensixtytwo · Sep 25, 2014 at 12:25 PM
It's much better to use AddForce with a derived direction, and using a ForceMode can dramatically change how it gets "thrown". Call this one in Start or on command, not in Update.
void ThrowDice() {
//Apply 10 units of force in the global Z-axis in one frame
rigidbody.AddForce(Vector3.forward * 10, ForceMode.Impulse);
}
And then check its velocity to see if it has stopped.
void Update() {
if (rigidbody.velocity.magnitude < 0.1) {
CheckFace();
}
}
Now for the fun part. Raycast from all local axes in order to see which side is touching the ground. Might want to use a tag or something for this.
rigidbody.AddForce(Vector3.forward * 10, Force$$anonymous$$ode.Impulse); This makes the Dice always go ahead. The tendency is to stop rolling in the given time
You only need one raycast if you cast down from above the dice. This will give you the face that's up, and the opposite face is 'down'
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
AddForce mechanism ? 1 Answer
OnCollisionEnter Sine Wave to Character 0 Answers
Projectile not moving properly in top down 2d shooter 2 Answers