Rotating player towards their heading - c#

I'm trying to replicate a movement system from an old flash game I'm basing a game I'm making in unity on (just for practice, mostly.) The main problem I have is that the player doesn't 'look' towards where he is going. He just looks in the direction all the time.
Here's what mine currently looks like
and here's what I want it to look like.
I've tried doing it but I couldn't find a solution that worked nicely (and the code for it is long gone). If someone could help me implement such a thing, that would be great!
The code for my player control:
public void PlayerFixedUpdate () {
if (Input.GetKey(KeyCode.A) && transform.position.x > -44){
if (body.velocity.x > -15){
body.AddForce(new Vector2(-15,0),ForceMode2D.Force);
}
}
if (Input.GetKey(KeyCode.D) && transform.position.x < 9){
if (body.velocity.x < 15){
body.AddForce(new Vector2(15,0),ForceMode2D.Force);
}
}
if (Input.GetKey(KeyCode.W) && transform.position.y < 24){
if (body.velocity.y < 15*body.mass){
body.AddForce(new Vector2(0,15),ForceMode2D.Force);
}
}
if (Input.GetKey(KeyCode.S) && transform.position.y > -1){
if (body.velocity.y > -15*body.mass){
body.AddForce(new Vector2(0,-15),ForceMode2D.Force);
}
}
}

Depends how your object is set up, but one solution would be to set the rotation in the direction of the velocity component.
void rotateFace()
{
Vector2 dir = rbody.velocity.normalized; // where rbody is your rigidbody2D
transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(dir.y, dir.x)*Mathf.Rad2Deg - 90); //may not need 90deg offset here
}
You may want to include a check for zero velocity, in which case you should do nothing to maintain the last rotation.

The second link shows like they are moving in one direction always and that is just the direction in which the character is facing, basically what they do is Just rotate the character using the player input and keep applying velocity in the local forward direction of the player.

Related

Make player follow a waypoint path but still be able to control player movement

I am developing a racing game where I have a predefined path with waypoints, and what I want to achieve is, I want my player to follow that general direction of the path but still be in full control of my player. As in, it keeps following the path, But I should be able to move it left and right to avoid obstacles.
Here is the piece of code I use right now.
#region Following the path
if (PathGenerator.instance.wayPoints.Count > 0)
{
Transform currentNode = PathGenerator.instance.wayPoints[currentNodeCount];
transform.position = Vector3.MoveTowards(transform.position, currentNode.position, forwardSpeed * Time.deltaTime);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(currentNode.position - transform.position), 1 * Time.deltaTime);
float distance = Vector3.Distance(transform.position, currentNode.position);
if(distance < 1f)
{
if(currentNodeCount < PathGenerator.instance.wayPoints.Count - 1)
currentNodeCount++;
}
}
#endregion
But the issue here Is that the player goes directly to the waypoint, even if I move it left and right. It would just go back to the center of the waypoint.
watch the gif:-
As you can see how it comes back to the center to follow the waypoint, I can't control the player like this. All I want is the player to follow the circuit path itself, but I want to control it's X-axis in order to avoid obstacle.
Can someone please guide me here and help me solve my problem? Any help or idea would be appreciated.
Thank you.
The below may not be the best solution to this problem, but shall help go further
You can setup the player as below
Player object with script and the character(capsule) as child
please check below image
player_heirarchy
and then with below code you will be allowed to move character side ways keeping the main object follow the waypoint.
Later you can add some limit to max side movement.
void Update()
{
//made a similar situation from your code
if (waypoints.Length > 0)
{
Transform currentNode = waypoints[currentNodeCount].transform;
transform.position = Vector3.MoveTowards(transform.position, currentNode.position, 10f * Time.deltaTime);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(currentNode.position - transform.position), 1 * Time.deltaTime);
float distance = Vector3.Distance(transform.position, currentNode.position);
if (distance < 1f)
{
if (currentNodeCount < waypoints.Length - 1)
currentNodeCount++;
}
}
// side movement to child object, in m case it is Player Object's second child
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.GetChild(1).Translate(Vector3.left * 5f * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.RightArrow))
{
transform.GetChild(1).Translate(Vector3.right * 5f * Time.deltaTime);
}
}
Also attaching the output video
Follow_waypoint_along_with_manual_side_movement
P.S. : This is my first answer, please forgive if not answered in correct format.

How can I rotate an object to face a target?

My bat stays still in the air.
How can i check that the player, that is moving right below on x axis, comes from the left or right side relative to the bat?
public class Bat : MonoBehaviour
{
Player player;
void Start()
{
player = FindObjectOfType<Player>();
}
void Update()
{
if (transform.InverseTransformPoint(player.transform.position).x >= 0)
transform.rotation = new Quaternion(transform.rotation.x, 0f, transform.rotation.z, 0f);
else
transform.rotation = new Quaternion(transform.rotation.x, -180f, transform.rotation.z, 0f);
}
}
As you may notice i try to flip the the Bat so it actually looks at the player.
First, don't use new Quaternion(...); unless you absolutely, 100% know quaternions inside and out. For instance, having the w component be 0 results in zero effective rotation. Also, quaternions use unitless figures and not degrees for their components. See here for a nice visualization of what different quaternion values might look like, under Quaternion).
Second, your logic is weird because if the bat has zero (identity) rotation, and the player is on the left of the bat, then your logic tries to* flip the bat 180 degrees, so that the player is now on the right side of the bat.
Then, the next frame assuming the bat and player are still in the same positions, the logic says oh the player is on the right side, set the rotation to zero (identity) rotation, which is of course what it was in the first place. So basically, you would have the bat rotate 180 degrees again so that the player is once again on the left side of the bat.
And so, you could get into a situation where every frame, the bat would flip a complete 180. Definitely not desired.
* I'm assuming if you had used Quaternion.Euler(transform.eulerAngles.x, 0f, transform.eulerAngles.z) etc.
Instead of concerning with any of that, use Vector3.Cross to find the forward the bat should point so its right faces the player's position. Then, use Quaternion.LookRotation to set the rotation of the bat to point in that forward direction:
void Update()
{
Vector3 batRightDir = player.transform.position - transform.position;
Vector3 batForwardDir = Vector3.Cross(batRightDir, Vector3.up);
if (batForwardDir.sqrMagnitude == Vector3.zero)
{
// player above or below bat. do nothing?
return;
}
transform.rotation = Quaternion.LookRotation(batForwardDir);
}
If you have the player on a different z as the bat, this will cause the bat to rotate around the y axis accordingly, which is what you would want from a 3d game, and could be a neat effect for a 2d game if you want that kind of effect.
If you want it to ignore the z position of the player, you could zero out the z component of batRightDir...
void Update()
{
Vector3 batRightDir = player.transform.position - transform.position;
batRightDir.z = 0; // ignore Z differences between bat and player
Vector3 batForwardDir = Vector3.Cross(batRightDir, Vector3.up);
if (batForwardDir.sqrMagnitude == Vector3.zero)
{
// player above or below bat. do nothing?
return;
}
transform.rotation = Quaternion.LookRotation(batForwardDir);
}
or it may be more intuitive to branch as you were previously:
void Update()
{
Vector3 batRightDir = player.transform.position - transform.position;
if (batRightDir.x > 0)
{
transform.rotation = Quaternion.identity;
}
else if (batRightDir.x < 0)
{
transform.rotation = Quaternion.LookRotation(Vector3.back);
}
else
{
// player above or below bat. do nothing?
}
}
You can get the access to his Rigidbody and than call it.
If Rigidbody.velocity.x > 0 he is moving to the right. If it's <0 it's moving to the left. All is related to X axis of course.

GetAxis("Vertical")

I'm trying to use GetAxis to get the value from the vertical axis of the player in my game. My goal here is for my code to see if the player is under .6 y, aka anything under .6 for his position to be changed back to the spawn point.
This is my code right here, Spawn is referred to a gameobject in Unity.
if (Input.GetAxis ("Vertical") < 0.6) {
transform.position = Spawn[0].position;
}
Not sure what you exactly mean by axis, but if you mean position is game you can use:
if (transform.position.y < 0.6f) {
transform.position = Spawn[0].position;
}

Unity - How to rotate an object based on touch?

I'm creating a game for iOS devices. I want my player or gameobject to rotate based on touch. I'm using the following code in touchPhase.Moved
if (Input.touchCount > 0 && Input.GetTouch (0).phase == TouchPhase.Moved)
{
coinTouched = true;
if (coinTouched)
{
Vector2 currentTouchPosition = Input.GetTouch (0).position;
endPos = new Vector3 (currentTouchPosition.x, 0, currentTouchPosition.y);
endTime = Time.time;
gameObject.transform.rotation = Quaternion.Euler(0f,Input.GetTouch(0).deltaPosition.x * 1.0f,0f);
}
}
But it is behaving awkward. it rotates good for almost 180 degree and then it moves in the opposite direction and after another 180 it rotates in the opposite direction and so on. Please help me.
Thank You.
Your code is a little weird. Meaning you use the x and y values in the wrong spots of the Vecotr. I'm going to assume you did this on purpose to get the cube to turn correctly. I would use the Rotate instead of changing the rotation value.
Here is a better than I can do:
http://answers.unity3d.com/questions/255118/rotating-an-object-with-touch.html

Get an object to wobble in Unity3D with C#

I am trying to simulate a boat in Unity3D. What I need it to be able to do is wobble like a real boat would while in water whenever it hits something. I have the boat colliding already, and all of its axes are unlocked. However, this means the boat will rotate, and then keep driving at an odd angle (like facing to the sky).
Is there a way to make the boat try to return to its original rotaions, without snapping to the exact values, but simply "rocking" back and forth, and then slowing down to eventually stop at the correct rotations again?
Here is the code am attempting to use:
void FixedUpdate ()
{
wobble();
}
void wobble()
{
if (this.transform.eulerAngles.x < 270)
{
this.rigidbody.AddTorque((float)19, (float)0, (float)0, ForceMode.Force);
}
else if (this.transform.eulerAngles.x > 270)
{
this.rigidbody.AddTorque((float)-19, (float)0, (float)0, ForceMode.Force);
}
else{}
if (this.transform.eulerAngles.z < 0)
{
this.rigidbody.AddTorque((float)19, (float)0, (float)0, ForceMode.Force);
}
else if (this.transform.eulerAngles.z > 0)
{
this.rigidbody.AddTorque((float)-19, (float)0, (float)0, ForceMode.Force);
}
else{}
}
However, now when my object hits something, it just starts spinning out of control. Any ideas?
You can use tweening. A wonderful technique to change values smoothly be-tween two values. In this case you can tween from your awkward bouncing angles to your boats sitting rotation by tweening between the two. There are good plugins to use like iTween which is fantastic but I will show you some half pseudo - half super-cereal code to get you started on the concept for "rotation correction"
Lets say I have my boat hit a nice big wave and its pointing my boat upwards to a 20deg angle.
My euler angle on X is 20 and I can return this to 0 by increasing the decreasing the value at a constant rate. I'm just showing X here but you can repeat the process for Z-axis. I would exclude Y as you will use your direction of your boat on Y and you don't want to screw up your boats navigation.
Update()
float angleDelta;
// check if value not 0 and tease the rotation towards it using angleDelta
if(transform.rotation.X > 0 ){
angleDelta = -0.2f;
} elseif (transform.rotation.X < 0){
angleDelta = 0.2f;
}
transform.rotation.X += angleDelta;
}
This incredibly simple implementation does the job but has the wonderful perk of being incredibly "snappy" and "jittery". So we want to add some smoothing to make it a more lifelike boat.
We do this by adding in a variable to the angleDelta:
Vector3 previousAngle;
float accelerationBuffer = 0.3f;
float decelerationBuffer = 0.1f;
Update()
Vector3 angleDelta;
//assuming that x=0 is our resting rotation
if(previousAngle.X > transform.rotation.X && transform.rotation.X > 0){
//speed up rotation correction - like gravity acting on boat
angleDelta.X += (previousAngle.X - transform.rotation.X) * accelerationBuffer;
} elseif(previousAngle.X < transform.rotation.X && transform.rotation.X > 0
//angle returning to resting place: slow down the rotation due to water resistatnce
angleDelta.X -= (previousAngle.X - transform.rotation.X) * deccelerationBuffer;
}
//If boat pointing to sky - reduce X
if(transform.rotation.X > 0 ){
transform.rotation.X -= angleDelta.X * Time.deltaTime;
//If boat diving into ocean - increase X
} elseif (transform.rotation.X < 0){
transform.rotation.X += angleDelta.X * Time.deltaTime; //Must not forget to use deltaTime!
}
//record rotation for next update
previousAngle = transform.rotation;
}
This is an incredibly rough draft but it gets across the theory that I'm trying to explain - you will need to adjust your own code accordingly as you haven't included any of your own (pastebin a snippet to us and maybe we can elaborate more!)

Categories

Resources