Smooth card rotation with Quaternion not doing anything
Summary
I am currently making a small game of match the pairs in Unity. To create the 'cards' I used 2 planes and put them back to back and grouped them in an empty object called Card. I created a prefab from this and duplicated them with an ID with them for example: Card1, Card2, Card3 etc.
In the CardScript.cs file which is attached as a component on every prefab is responsible for the movement of these cards. I started the scene by showing the player the cards (front side up) and then turn 190 degrees after a delay. When the player hovers over the cards, the card's material tint changes colour and when the player moves the cursor somewhere else, the card changes the material tint back to normal.
Problem
I want the card to turn to the front side up by clicking on it so I used the OnMouseDown() method in Unity. This is currently my code in the Update() method:
void Update()
{
if (startCheck)
{
transform.rotation = Quaternion.RotateTowards(transform.rotation, beginRotation, flipSpeed * Time.deltaTime); //used for start sequence
}
if (mouseEnter)
{
Transform child = gameObject.transform.FindChild("CardBack");
child.GetComponent<Renderer>().material.color = Color.Lerp(child.GetComponent<Renderer>().material.color, Color.red, hoverOverSpeed * Time.deltaTime);
if (clicked)
{
transform.rotation = Quaternion.RotateTowards(transform.rotation, beginRotation, flipSpeed * Time.deltaTime);
}
}
else
{
Transform child = gameObject.transform.FindChild("CardBack");
child.GetComponent<Renderer>().material.color = Color.Lerp(child.GetComponent<Renderer>().material.color, Color.white, hoverOverSpeed * Time.deltaTime);
}
}
However, whenever I press a card after the starting rotation, nothing happens. I have tried multiple other ways even by trying to make the rotation immediate by using for example transform.Rotate but still, nothing worked. But, I know it is something I'm doing wrong because I did a Debug.Log in the 'if (clicked)' statement instead of the attempt of rotating the card and the Debug.Log worked. Can anyone tell me what I am doing wrong and how to fix it? Also, I only recently delved into Unity like this so I appreciate if people simplify things for me too. :)
P.S. I also hope I posted this correctly since this is my first question so sorry if I did this wrong!
Key
startCheck is a boolean which is only set to true after the delay. This causes the cards to do the flip animation in the beginning (after the delay).
beginRotation is a Quaternion used to make the cards flip properly by making them turn Vector3.forward for 180 degrees.
flipSpeed is self-explanatory.
mouseEnter is a boolean which is set to true after the user hovers the cursor over a card and is set to false whenever he moves the cursor somewhere away from the card.
clicked is a boolean which is set to true after the player presses on a card.
just to clarify, beginRotation is used to turn the card upside down, or up?
@hexagonius beginRotation is used to make the cards flip with their back side up. How the game works is that in the beginning, the scene shows the cards to the player what their pattern/image is and then after a delay of 2 seconds, the cards flip over to show their back side. To show their back side, the cards use the beginRotation Quaternion. However, I used it again in the if (clicked) statement just to make it turn 180 degrees again. Could that be what's wrong?
ok, then that's the problem. a Quaternion is an orientation in space. like the Quaternion.identity always is "look forward with your up vector up". right now your code tries to rotate the cards face down where they are already.
either create another Quaternion with a 180 degree opposite from your beginRotation, which might just be Quaternion.Identity, or save the start rotation of the cards at the beginning when they face up and use that
I would use animations with an Animator Controller for this kind of thing. You would create animation states with a condition based on a boolean parameter. Then you simply have to change that boolean parameter via the code. Simple, and very flexible.
@jikkou The only reason I wouldn't use that method is because we haven't learned how to use it at school and I don't want to delve too much into making this. If possible, all I want is a way on how I could fix this problem by using a Quaternion method. So if you know a way, please do inform me.
Hum, I personally don't like those implementations, sometimes given in the docs, where you use the current state as a start state. It gives a damping effect, which can be nice, but over which you have no control.
Usually, I prefer to do interpolations between two static states, like :
private bool clicked;
private float slerpAmount = 0;
private Quaternion slerpStart;
private Quaternion slerpEnd = Quaternion.identity;
void On$$anonymous$$ouseUpAsButton ()
{
clicked = true;
slerpStart = transform.rotation;
}
void Update()
{
if (clicked)
{
slerpAmount += Time.deltaTime;
if (slerpAmount <= 1)
{
transform.rotation = Quaternion.Slerp(slerpStart, slerpEnd, slerpAmount);
}
else
{
slerpAmount = 0;
clicked = false;
}
}
}
Answer by andracer108 · Dec 12, 2016 at 10:38 AM
@jikkou Thank you, I'll try this out whenever I have the chance and will get back to you with the result. :)
EDIT: I have fixed the problem by using Lerp and by leaving beginRotation as is and adding a chosenRotation which is set to Quaternion.identity.
Here's the code used in the if (clicked) statement:
if (clicked)
{
transform.rotation = Quaternion.Lerp(transform.rotation, chosenRotation, 5 * (currentTurnTime / 2)); //choosing a card
}
currentTurnTime is a variable which is found in Update() and is set to Time.deltaTime and is also reset to 0 whenever OnMouseUpAsButton() is activated.
Thank you all for the help! :)