How to add friction to a Wheel of Fortune in Unity3D - unity3d

First of all I am new to unity as will as C#. I want to create a Wheel of Fortune for my game using C# where you can rotate it with the mouse. I wrote this code in C# - it works well, the only problem is I don’t know how to add friction to it so that if I release the mouse button it still continues rotating and slows down until it is fully stopped (Just like a realistic Fortune Wheel).
using UnityEngine;
using System.Collections;
public class RotateCSharp : MonoBehaviour
{
public int speed;
public float lerpSpeed;
float xDeg;
float yDeg;
Quaternion fromRotation;
Quaternion toRotation;
void Update()
{
if (Input.GetMouseButton(0))
{
xDeg -= Input.GetAxis("Mouse X") * speed;
fromRotation = transform.rotation;
toRotation = Quaternion.Euler (yDeg,xDeg,0);
transform.rotation = Quaternion.Lerp(fromRotation, toRotation, Time.deltaTime * lerpSpeed);
}
}
}
How can I accomplish this?

Full Disclosure--I don't do Unity, and not much C#, but this is mostly math.
Friction from sliding or rolling is almost exactly constant deceleration. Deceleration is negative acceleration, and acceleration is (velocity change)/(elapsed time).
Figure out how long you want the wheel to spin at a the maximum initial angular speed you'll allow, and that speed/time ratio is your deceleration rate. That's a constant for the wheel.
Now, in the code either before or after adjusting the angular position, decrease the speed by the deceleration rate * time interval, being careful not to overshoot 0:
if (speed > 0)
speed = Math.max(0, speed - decelRate*Time.deltaTime);
else
speed = Math.min(0, speed + decelRate*Time.deltaTime);
That assumes that decelRate is a positive value, and will handle spins in either direction.
You may have to adjust the syntax a bit, but that's the basic idea.

I've put together a behaviour that applies friction on a hinge joint. Here it is:
using UnityEngine;
public class JointFriction : MonoBehaviour {
[Tooltip("mulitiplier for the angular velocity for the torque to apply.")]
public float Friction = 0.4f;
private HingeJoint _hinge;
private Rigidbody _thisBody;
private Rigidbody _connectedBody;
private Vector3 _axis; //local space
// Use this for initialization
void Start () {
_hinge = GetComponent<HingeJoint>();
_connectedBody = _hinge.connectedBody;
_axis = _hinge.axis;
_thisBody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate () {
var angularV = _hinge.velocity;
//Debug.Log("angularV " + angularV);
var worldAxis = transform.TransformVector(_axis);
var worldTorque = Friction * angularV * worldAxis;
_thisBody.AddTorque(-worldTorque);
_connectedBody.AddTorque(worldTorque);
}
}
You can apply this as a separate behaviour to the object with the hinge joint, or you can take bits of it and incorporate them into your behaviour.
This code assumes the hinge joint has a connected rigidbody that it is rubbing against, if that is not the case, simply remove the lines that refer to the _connectedRigidbody.

Related

Car gets stuck on waypoint

I have an automatic rigidbody car that is supposed to follow a set of waypoints on a mesh collider map but will get caught on any random waypoint and will rotate about that waypoint. Here is my code for the automatic car:
public class FollowThePath : MonoBehaviour
{
public Transform[] target;
public float speed;
public float damping = 6.0f;
public GameObject centerOfMass;
private int current;
void Start()
{
GetComponent<Rigidbody>().centerOfMass = centerOfMass.transform.localPosition;
}
void Update()
{
if (transform.position != target[current].position)
{
Vector3 pos = Vector3.MoveTowards(transform.position, target[current].position, speed * Time.deltaTime);
GetComponent<Rigidbody>().MovePosition(pos);
var rotation = Quaternion.LookRotation(target[current].position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
}
else current = (current + 1) % target.Length;
}
}
I increased the mass, added a center of mass, froze the y axis position and rotation, lowered the center of mass. I noticed that the car gets stuck particularly, but not limited to curves.
Comparing two Vector3s for equality is generally a bad idea when handling moving objects.
Firstly because they use float internally, which always run the risk of being imprecise.
Secondly because Unity knows this and approximates the equality of two vectors internally. The problem is, that you don't have control over the precision being used by unity. When you implement it yourself like the function below it should be easier for you to figure out if that's the problem.
What's most likely the case is, that if (transform.position != target[current].position) never evaluates to false, since transform.position is (0,0,0) and target[current].position is (0.00000000001,0,0) or something. They are almost equal, but not quite equal, at least using the == operator. Then your code in else is never executed.
You can try something like this, where allowedDifference should be in the scope of 0.0001 for ~0.1m precision, or 0.00000001 for ~0.1mm precision:
public bool ApproximatelyEquals(Vector3 a, Vector3 b, float allowedDifference = 0.00000001f){
return Vector3.SqrMagnitude(a - b) < allowedDifference;
}
//Edit:
To clarify, use it like:
if(!ApproximatelyEquals(transform.position, target[current].position), 0.00000001f)

How to add friction to Unity HingeJoint?

I attach a rigidbody to a HingeJoint in Unity.
It's attached no at the the center of an anchor of a joint.
To stop it from falling I set Use Motor = true, Target Velocity = 0 and apply some force to the motor.
However, this does not help, see video:
http://g.recordit.co/JJ0cmfT1Mb.gif
Here is the sample project: https://drive.google.com/open?id=0B8QGeF3SuAgTNnozX05wTVJGZHc
Screen to reproduce the issue (there is no code):
How can I apply a friction to a joint to stop rigidbody from moving?
Setting spring with damper or applying a limit is not an option for me, because I need to rotate the rigidbody correctly when I apply enough torque (force) to a motor.
If I switch damper/limit on and off, the rigidbody will move faster when it is rotated in a direction of falling and slower when it is rotated in opposite direction.
I've put together a behaviour that applies friction on a hinge joint. Here it is:
using UnityEngine;
public class JointFriction : MonoBehaviour {
[Tooltip("mulitiplier for the angular velocity for the torque to apply.")]
public float Friction = 0.4f;
private HingeJoint _hinge;
private Rigidbody _thisBody;
private Rigidbody _connectedBody;
private Vector3 _axis; //local space
// Use this for initialization
void Start () {
_hinge = GetComponent<HingeJoint>();
_connectedBody = _hinge.connectedBody;
_axis = _hinge.axis;
_thisBody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate () {
var angularV = _hinge.velocity;
//Debug.Log("angularV " + angularV);
var worldAxis = transform.TransformVector(_axis);
var worldTorque = Friction * angularV * worldAxis;
_thisBody.AddTorque(-worldTorque);
_connectedBody.AddTorque(worldTorque);
}
}
This answers the headline of your question, and is what I was looking for when I found it. However this probably won't work for what you want from your more detailed description.
This applies friction that is proportional to the angular velocity, if there's no angular velocity, no force is applied. This means that under a constant force, like gravity in your example, it will always move at some reduced speed. In reality, imperfections in materials and other real world messiness mean that applying friction to joints can keep them still against a constant torque, but in a game engine, you will need some other torque to counter your constant force.
It sounds like you don't want gravity. You can just turn gravity off in the rigid body's inspector.

Unity ball with constant speed

I'm making 2D mobile game and I have a ball, but my ball doesn't have a constant moving speed. What I need to do?
When I build game on my android device, ball have a various speed. In that case, my game is not playable.
I hope that someone can help me. Thanks.
This is on my start function:
void Start () {
GetComponent<Rigidbody2D> ()
.AddForce (new Vector2 (1f, 0.5f)* Time.deltaTime * force);
}
Is it a good practice if I used in code " Application.LoadLevel ("__Scena_0"); " to load existing scene when I lose " life" ? Problem happens when I lost " life " and try playing game in second chance.
My update function is about OnTriggerEnter2D when my ball hit trigger objects.
EDIT 23.12.2015. : problem solve with adding physics material (fiction 0) and adding to script:
using UnityEngine.SceneManagement;
...
SceneManager.LoadScene ("MainScene");
The problem is the calculation of the force vector:
new Vector2 (1f, 0.5f) * Time.deltaTime * force
You are using Time.deltaTime as a factor, which means that the applied force is not constant, but depending on the deltaTime, which is the duration of the last frame. This explains why it changes randomly.
I don't think Time.deltaTime is what you want here, try just removing the factor and adjusting the "force" factor accordingly. You should now have a constant force applied, independent from the platform you play on.
Create a new Physics Material, set friction zero and add it to your object. If your object has no friction, its speed cannot be decreased. Then, use AddForce() on Rigidbody2D to speed up.
Assuming that your ball and colliding walls have bouncy materials with no friction. Try
public float _ballSpeed = 2.5f;
Rigidbody2D _rb;
void Start()
{
_rb = GetComponent<Rigidbody2D>();
_rb.velocity = Vector2.one * _ballSpeed;
}
void Update()
{
}
From this you can control ball speed through _ballSpeed
//========== OR ==========//
If you want to retain speed even after ball destruction.
Retain _ballSpeed in any global static variable.
Suppose you have a class named Globals, declare a variable like,
public class Globals
{
public static float BALL_SPEED = 2.5f;
}
Now in Ball Script
Rigidbody2D _rb;
void Start()
{
_rb = GetComponent<Rigidbody2D>();
_rb.velocity = Vector2.one * Globals.BALL_SPEED;
}
void Update()
{
}

Camera Move and Rotate Follow Player very jerky

I make a character move on the surface of a circle. I let the camera move and rotate follow character. But the camera move and rotate very jerky. If I increase the value of the third parameter, the shock increases. and to reduce the value of the third parameter, the camera does not rotate to keep up the character. Help me fix it
My Code Camera Follow Player
public class CameraFollow : MonoBehaviour
{
public Transform player;
GameController gc;
public float speed = 2;
Vector3 pos = new Vector3 (0, 0, -10);
// Use this for initialization
void Start ()
{
gc = FindObjectOfType (typeof(GameController)) as GameController;
}
void FixedUpdate ()
{
if (gc.gameState == GameController.GameState.playing || gc.gameState == GameController.GameState.changeWave) {
transform.position = player.position + pos;
transform.rotation = Quaternion.Slerp (transform.rotation,
player.transform.rotation,
speed * Time.deltaTime);
}
}
}
Setting the position of a transform inside of FixedUpdate is a red flag for sure, especially when you're reporting that it's "jerky". Fixed update happens at an irregular interval compared to the frames displayed. This is because Physics needs to update using a fixed time step. The reason why this is the case is out of scope for this question.
Long story short, try changing FixedUpdate to Update and that should fix things looking "jerky".
Let me know if this doesn't work and I'll look for other possible causes.
If you are using a Rigidbody2D to move the character, make sure to set its Interpolate property to 'Interpolate'. This should fix it.

Unity approach an object in spiral motion

In Unity I can handle circular motion around an object with a simple
transform.RotateAround(GameObject.Find("CubeTest").transform.position, Vector3.up, 20000*Time.deltaTime);
However, I want the object traveling in circular motion to approach this object whilst in orbit. Not entirely sure how to do this without screwing up.
GameObject cube = GameObject.Find("CubeTest");
transform.LookAt(cube.transform);
transform.Translate(transform.forward * Time.deltaTime * approachSpeed);
transform.RotateAround(cube.transform.position, Vector3.up,20000*Time.deltaTime);
I think that could do as you want? It moves towards the rotation point gradually, then rotates, giving the appearance of a deteriorating orbit.
If you came here looking for working 2D solution here you are.
From this blog post. I built this configurable script:
public class SpiralMovement : MonoBehaviour
{
[SerializeField] Transform moveable;
[SerializeField] public Transform destiny;
[SerializeField] float speed;
// As higher as smoother approach, but it can not be more than 90, or it will start getting away.
[SerializeField][Range(0f, 89f)] float angle = 60f;
void Update()
{
Vector3 direction = destiny.position - moveable.position;
direction = Quaternion.Euler(0, 0, angle) * direction;
float distanceThisFrame = speed * Time.deltaTime;
moveable.transform.Translate(direction.normalized * distanceThisFrame, Space.World);
}
}