I have a gravity thing and when they touch the ceiling I want the player to flip, my code doesn't work and I wonder if there is a better way to do this. I'd also like to know how to make the player not rotate to those exact coordinates and just where the player is already facing.
IEnumerator GravitySwitch()
{
if (Input.GetMouseButtonDown(1) && grounded)
{
Physics.gravity = new Vector3(0, 10.0f, 0);
yield return new WaitForSeconds(0.2f);
if (grounded)
transform.localEulerAngles = new Vector3(0, 0, 180);
}
if (Input.GetMouseButtonDown(0) && grounded)
{
Physics.gravity = new Vector3(0, -10.0f, 0);
yield return new WaitForSeconds(0.2f);
if (grounded)
transform.localEulerAngles = new Vector3(0, 0, 0);
}
}
You could multiply the scale of your player's scale vector by:
new Vector3(1, -1, 1);
can try
transform.Rotate(0.0f, 0.0f, 180.0f, Space.Self);
https://docs.unity3d.com/ScriptReference/Transform.Rotate.html
Related
I was making a function so that my object can turn around. So I made this function:
void Drehen(){
if(Input.GetAxis("Horizontal") > 0.1){
transform.Rotate(new Vector3(0f, 0f, 0f));
vorne = true;
}
if(Input.GetAxis("Horizontal") > -0.1){
transform.Rotate(new Vector3(0f, 180f, 0f));
vorne = false;
}
}
The function checks the input if the player goes forwards or backwards and rotates him in the direction via transform.Rotate(new Vector3(0f, 180f, 0f));
Now, every time I start the game I am able to go forward but as soon as I go backward it flips every side every frame.
Well that's pretty obvious.
Rotate rotates the object from the current rotation about the given amount so
transform.Rotate(0, 0, 0);
does absolutely nothing at all and in
transform.Rotate(0, 180, 0);
you rotate it by 180° every frame.
In the second condition you have > -0.1 which is the case all the time while you don't press the negative key.
It should probably rather be < 0.1f.
What you want is probably rather e.g.
var horizontal = Input.GetAxis("Horizontal");
if(horizontal > 0.1f)
{
// or localRotation depending on your needs
transform.rotation = Quaternion.identity;
vorne = true;
}
else if(horizontal < 0.1f)
{
transform.rotation = Quaternion.Euler(0f, 180f, 0f);
vorne = false;
}
Or actually as alternative you could also do
var horizontal = Input.GetAxis("Horizontal");
if(Mathf.Abs(horizontal) > 0.1f)
{
transform.forward = new Vector3(0, 0, horizontal);
}
Try using
transform.eulerAngles = new Vector3(0f, 180f, 0f);
I have a scene that is as follows:
I have the player object, which is a Z locked cube that I move around with a script, using various AddForce calls. The important method in there is this one:
public void SetDirections(Vector3 down)
{
down.Normalize();
this.down = down;
forward = Vector3.Cross(down, new Vector3(0, 0, 1));
}
Other code relating to rotation in the same script is this:
void Turning ()
{
// Irányitó gombok hatására a Taxi elforduljon 180fokot
Vector3 lookDirection = forward;
// balra forditás
if (inputh > 0)
{
faceLeft = false;
}
// jobbra forditás
if (inputh < 0)
{
faceLeft = true;
}
if (faceLeft)
{
lookDirection *= -1;
}
transform.LookAt(transform.position + lookDirection, new Vector3(0, 1, 0));
}
I have this bit on another object in the scene:
public class RotateGravity : MonoBehaviour
{
public GameObject Taxi;
public float MinLimit, MaxLimit;
private TaxiController tControl;
private Rigidbody tRigidbody;
private Transform tTransform;
void Start()
{
tControl = Taxi.GetComponent<TaxiController>();
tRigidbody = Taxi.GetComponent<Rigidbody>();
tTransform = Taxi.GetComponent<Transform>();
}
void OnTriggerStay()
{
Vector3 originalDown = tControl.Down;
Vector3 newDown = tTransform.position - gameObject.transform.position;
if (Vector3.SignedAngle(newDown, new Vector3(1, 0, 0), new Vector3(0, 0, 1)) > MinLimit &&
Vector3.SignedAngle(newDown, new Vector3(1, 0, 0), new Vector3(0, 0, 1)) < MaxLimit)
{
newDown.Normalize();
tControl.SetDirections(newDown);
float angle = Vector3.SignedAngle(originalDown, newDown, new Vector3(0, 0, 1));
tRigidbody.velocity = Quaternion.AngleAxis(angle, new Vector3(0, 0, 1)) * tRigidbody.velocity;
}
Debug.Log("Stay: " + newDown);
}
void OnTriggerExit()
{
float angle = Vector3.Angle(tTransform.position - gameObject.transform.position, new Vector3(1, 0, 0));
Vector3 newDown;
float newAngle;
if (Mathf.Abs(angle - MinLimit) < Mathf.Abs(angle - MaxLimit))
{
newDown = Quaternion.AngleAxis(MinLimit, new Vector3(0, 0, -1)) * new Vector3(1, 0, 0);
newAngle = MinLimit;
}
else
{
newDown = Quaternion.AngleAxis(MaxLimit, new Vector3(0, 0, -1)) * new Vector3(1, 0, 0);
newAngle = MaxLimit;
}
Debug.Log("Exit: " + newDown + " " + newAngle);
tControl.SetDirections(newDown);
tRigidbody.velocity = Quaternion.AngleAxis(newAngle, new Vector3(0, 0, 1)) * tRigidbody.velocity;
}
}
Basically the idea is that the gravity direction changes as the player moves along the object, so just by moving right it would revolve around the object between the MinLimit and MaxLimit angles. Which it does. At the end I want to fix the direction to these limits and this is where a weird thing happens. In my example I have the MinLimit at 0 and the MaxLimit at 90. Meaning that the player enters horizontally from the left, and gravity changes from (0, -1, 0) to (1, 0, 0). Except, at the end the player object rotates 90 degrees around its forward vector.
Can somebody explain where I'm going wrong? I hate rotations in Unity :(
In the video below the red sphere is just an indicator under the player object to show better its facing.
https://www.youtube.com/watch?v=z4p9UQb7inA
Okay, I was not setting the up vector correctly in the Turning() method, it pointed in the positive Y direction, so when my forward direction ended up being the same it didn't know where to rotate the object on that axis. I'm dumb. I set the up vector to point to -1 * down, and boom, it worked.
so i don't know if i explained it properly in the title, but what i'm trying to do is by clicking Q or E rotate object around the Y axis, but at the same time i'm raycasting to the ground to check the point rotation to face it in to the right direction.
To clarify this, here is an example:
I'm trying to place the fireplace, i'm on the hill. To prevent the fireplace go into the terrain, i need to rotate it so that i would "stick" to the terrain by it's bottom, but then i want to rotate it around the Y a couple of degrees..
Here is the code that i've got:
using UnityEngine;
public class Foobar : MonoBehaviour
{
Transform cam;
Transform prefabAsTransform;
Vector3 currentPos;
float addToY = 0.5f;
int mask;
void Start()
{
cam = Camera.main.transform;
prefabAsTransform = transform;
mask = LayerMask.GetMask("Default");
}
void Update()
{
RaycastHit hit;
if (Physics.Raycast(cam.position, cam.forward, out hit, Mathf.Infinity, mask))
{
currentPos = new Vector3(hit.point.x, hit.point.y + addToY, hit.point.z);
prefabAsTransform.position = currentPos;
prefabAsTransform.transform.up = hit.normal;
}
if (prefabAsTransform != null)
{
if (Input.GetKeyDown(KeyCode.Q))
{
if (Input.GetKey(KeyCode.LeftControl))
{
prefabAsTransform.Rotate(new Vector3(0, 1, 0));
}
else
{
prefabAsTransform.Rotate(new Vector3(0, 10, 0));
}
}
if (Input.GetKeyDown(KeyCode.E))
{
if (Input.GetKey(KeyCode.LeftControl))
{
prefabAsTransform.Rotate(new Vector3(0, -1, 0));
}
else
{
prefabAsTransform.Rotate(new Vector3(0, -10, 0));
}
}
}
}
}
The problem here is that it's facing the terrain without any issues, but i'm unable to rotate it around Y by myself. I assume that's due to the fact, that i'm constantly updating the rotation, but i have no idea how to change that.
Yes, it's because you are setting the rotation every frame with prefabAsTransform.transform.up = hit.normal; and not taking the current forward direction into account.
Instead, you should use prefabAsTransform.rotation = LookRotation(newForward, newUp); But, how can you use the current forward to determine newForward? You can use cross products for that. This worked for me:
void Update()
{
RaycastHit hit;
if (Physics.Raycast(cam.position, cam.forward, out hit, Mathf.Infinity, mask))
{
currentPos = new Vector3(hit.point.x, hit.point.y + addToY, hit.point.z);
prefabAsTransform.position = currentPos;
Vector3 newUp = hit.normal;
Vector3 oldForward = prefabAsTransform.forward;
Vector3 newRight = Vector3.Cross(newUp, oldForward);
Vector3 newForward = Vector3.Cross(newRight, newUp);
prefabAsTransform.rotation = Quaternion.LookRotation(newForward, newUp);
}
if (prefabAsTransform != null)
{
if (Input.GetKeyDown(KeyCode.Q))
{
if (Input.GetKey(KeyCode.LeftControl))
{
prefabAsTransform.Rotate(new Vector3(0, 1, 0));
}
else
{
prefabAsTransform.Rotate(new Vector3(0, 10, 0));
}
}
if (Input.GetKeyDown(KeyCode.E))
{
if (Input.GetKey(KeyCode.LeftControl))
{
prefabAsTransform.Rotate(new Vector3(0, -1, 0));
}
else
{
prefabAsTransform.Rotate(new Vector3(0, -10, 0));
}
}
}
}
i'm currently in progress of a new game where my character has to move. While my character walks forward and i'm rotating it on the z axis, it just rotates instead of walking down the new z axis.
void Update()
{
{
if (Input.GetKeyDown(KeyCode.W))
{
anim.SetInteger("Condition", 1);
moveDir = new Vector3(0, 0, 1);
moveDir *= speed;
moveDir = transform.TransformDirection(moveDir);
}
if (Input.GetKeyUp(KeyCode.W))
{
anim.SetInteger("Condition", 0);
moveDir = new Vector3(0, 0, 0);
}
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
rot += Input.GetAxisRaw("Horizontal") * rotSpeed * Time.deltaTime;
transform.eulerAngles = new Vector3(0, rot, 0);
}
}
I want to be able to walk forward while changing the z axis instead of walking then stop and then walk again.
You can't do that using a CharacterController because your call to controller.move() overwrites the rotation ... you need to write a custom move function.
I've followed a tutorial on how to make a first person camera rotate and move in a 3D world in XNA on the Microsoft website. But when I rotate the camera along it's Y axis, it doesn't move the direction it is rotated/facing, instead it moves as if it was facing the direction it was originally faced.
Here's my code:
static Vector3 avatarPosition = new Vector3(0, 0, 0);
static Vector3 cameraPosition = avatarPosition;
Vector3 cameraReference = new Vector3(10, 0, 0);
// Create a vector pointing the direction the camera is facing.
Matrix world = Matrix.CreateWorld(new Vector3(0, -1, 0), Vector3.Forward, Vector3.Up);
Matrix rotationMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(0));
int Rot = 0;
Vector3 worldVector = new Vector3(5,-2, 0);
Matrix view, proj;
Vector3 cameraLookat;
Update()
{
world = Matrix.CreateWorld(worldVector, Vector3.Forward, Vector3.Up);
if (IsKeyDown(Keys.W))
avatarPosition += new Vector3(0.2f, 0f, 0);
if (IsKeyDown(Keys.S))
avatarPosition += new Vector3(-0.2f, 0f, 0);
if (IsKeyDown(Keys.A))
avatarPosition += new Vector3(0f, 0f, -0.2f);
if (IsKeyDown(Keys.D))
avatarPosition += new Vector3(0f, 0f, 0.2f);
if (IsKeyDown(Keys.Left))
Rot += 1;
if (IsKeyDown(Keys.Right))
Rot += -1;
rotationMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(Rot));
// Create a vector pointing the direction the camera is facing.
Vector3 transformedReference = Vector3.Transform(cameraReference, rotationMatrix);
// Calculate the position the camera is looking at.
cameraLookat = transformedReference + cameraPosition;
// Set up the view matrix and projection matrix.
view = Matrix.CreateLookAt(cameraPosition, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f));
proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), graphics.GraphicsDevice.Viewport.AspectRatio,
0.1f, 1000);
cameraPosition = avatarPosition;
}
Can someone please tell me why the camera does not travel the way it is rotated? Or can someone please just give me the damn code to make one?
I appears the problem you are experiencing is coming from this area of the code:
if (IsKeyDown(Keys.W))
avatarPosition += new Vector3(0.2f, 0f, 0);
if (IsKeyDown(Keys.S))
avatarPosition += new Vector3(-0.2f, 0f, 0);
if (IsKeyDown(Keys.A))
avatarPosition += new Vector3(0f, 0f, -0.2f);
if (IsKeyDown(Keys.D))
avatarPosition += new Vector3(0f, 0f, 0.2f);
Instead of translating the avatarPosition directly along the x or z axis, it should be using the direction you're pointing which appears to be your transformedReference variable.
For instance, to move forward the way the camera is facing:
if (IsKeyDown(Keys.W))
avatarPosition += transformedReference;
However, since the transformedReference variable appears to be normalized, it may not move the avatar the distance you'd hoped. In that case simply multiply it by some constant MOVEMENT_SPEED for something like such:
if (IsKeyDown(Keys.W))
avatarPosition += transformedReference * MOVEMENT_SPEED;