I am having some trouble with a piece of code that I am working on in C#.
What this code is meant to do is move the player up and forward so that he is standing on a 1x1x1 block in front of him and not allow him to get over anything that is 1x2x1 or higher. but I am having a problem , Image. The further away I get from 0,0,0 the worse it gets. could anyone help me?
Code:
//Player Climbs Up One Block Heights But Dose Not Climb Anything Higher
if ((PlayerClimAction.posOneHit == true) && (PlayerClimAction.posTwoHit == false))
{
// Moves the Player Up By 0.9
controller.Move ((transform.position + transform.up * (float) 0.9f) * Time.deltaTime);
// Moves The Player Forward By 0.9
controller.Move ((transform.TransformDirection (input) * (float) 0.9f) * Time.deltaTime);
//Debug
print("Up Vector3: " + (transform.position + transform.up * (float) 0.9f) * Time.deltaTime);
print("////////////////////////////////////////////////");
print ("Forward: " + (transform.TransformDirection (input) * (float) 0.9f) * Time.deltaTime);
// Reset Triggers
PlayerClimAction.posOneHit = false;
PlayerClimAction.posTwoHit = false;
}else
{
controller.Move (motion * Time.deltaTime); // Move Normaly
}
Big thanks to Tone for the information. Thanks to that I was able to edit my code and change it to this:
//Player Climbs Up One Block Heights But Dose Not Climb Anything Higher
if ((PlayerClimAction.posOneHit == true) && (PlayerClimAction.posTwoHit == false))
{
// Moves the Player Up By 0.5
controller.Move ((transform.up * (float) 0.5f));
// Moves The Player Forward
controller.Move (motion * Time.deltaTime); // Move Normaly
// Reset Triggers
PlayerClimAction.posOneHit = false;
PlayerClimAction.posTwoHit = false;
}else
{
controller.Move (motion * Time.deltaTime); // Move Normaly
}
I changes the forward movement in the climb to just be a duplicate of the regular movement in the else statement, because that is the distance and speed that the player would move normally, and because of Tone's suggestion that I should change controller.Move ((transform.position + transform.up * (float) 0.9f) * Time.deltaTime); to controller.Move (transform.up * (float) 0.9f * Time.deltaTime); really helped me out in smoothing things out.
TY to all who looked at the post.
On the assumption that the argument to controller.Move is a movement vector rather than an absolute position (that's what the rest of your code suggests)
The line
controller.Move ((transform.position + transform.up * (float) 0.9f) * Time.deltaTime);
should read
controller.Move (transform.up * (float) 0.9f * Time.deltaTime);
If on the other hand the argument to controller.Move should be an absolute position you have several issues
a) the first call to controller.Move multiplies transform.position by Time.deltaTime. This will result in movement on all axes (and is why it gets worse the further away from 0,0,0)
b) the second and third calls to controller.Move don't include transform.Position in the calculation (depending on what transform.TransformDirection and mostion represent). Also I assume that is a typo and should be motion.
Related
void UpdateMovement()
{
Vector2 targetDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
targetDir.Normalize();
currentDir = Vector2.SmoothDamp(currentDir, targetDir, ref currentDirVelocity, moveSmoothTime);
if (controller.isGrounded)
{
velocityY = -gravity;
}
// jump
if (controller.isGrounded && Input.GetKeyDown(KeyCode.Space))
{
velocityY = jumpForce;
}
// sprint
if (Input.GetKey(KeyCode.LeftShift))
{
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * sprintSpeed + Vector3.up * velocityY;
}
else
{
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * walkSpeed + Vector3.up * velocityY;
}
velocityY -= gravity * Time.deltaTime;
Debug.Log(velocityY);
controller.Move(velocity * Time.deltaTime);
}
This is the code that I am using to move and jump in my game. Those functions work fine, the problem is in the gravity when walking off a surface. When jumping gravity works as intended but when falling without jumping (walking off the edge) gravity is still set to it's default value (15) so the characters falls incredibly fast.
I understand that this is caused by having no function to change this value when falling from an edge but I have found no way of making this happen without breaking all of the vertical movement.
You can reset the gravity as Brackeys did in his FPS Controller Tutorial:
if (isGrounded) {
velocityY = -2f;
}
I know this has been asked but can't figure out how to solve this.
if (this.gameObject.tag == "1Team"){
unitGO.transform.position += transform.right * movementSpeed * Time.deltaTime;
} else if (this.gameObject.tag == "2Team"){
unitGO.transform.position += transform.left * movementSpeed * Time.deltaTime;
}
Unity marks in red transform.left ( Transform' does not contain a definition for 'left' ), so I dont know how to move my character to the left. I have tried using -Transform.right, Transform.right * -movementSpeed, new Vector3( - 1,0,0), unitGO.transform.position -= new Vector3(1,0,0) * movementSpeed * Time.deltaTime; and other options without getting the movement I want.
if I change the tag from the GameObject I want to move, it actually moves right, so I dont think it's anything related to attaching scripts
https://docs.unity3d.com/ScriptReference/Vector3-left.html
Any suggestions?
Thank you
While Vector3.left exists, for Transform there is only transform.right.
Which is no problem since for moving left you simply use -transform.right.
Now note that your intempts of using new Vector3 also didn't work since if you use that you move in global space along Unity's X axis .. not in local space.
Now there are multiple possible solutions:
For moving in your local space do e.g.
if (gameObject.CompareTag("1Team"))
{
unitGO.transform.position += transform.right * movementSpeed * Time.deltaTime;
}
else if (gameObject.CompareTag("2Team"))
{
unitGO.transform.position -= transform.right * movementSpeed * Time.deltaTime;
// Same as
//unitGO.transform.position += -transform.right * movementSpeed * Time.deltaTime;
}
Or if you wan to move in Unity's global X axis then
if (gameObject.CompareTag("1Team"))
{
unitGO.transform.position += Vector3.right * movementSpeed * Time.deltaTime;
}
else if (gameObject.CompareTag("2Team"))
{
unitGO.transform.position += Vector3.left * movementSpeed * Time.deltaTime;
// Same as
//unitGO.transform.position -= Vector3.right * movementSpeed * Time.deltaTime;
}
Or if you actually rather wanted to move along the local X axis of the object you are moving you could rather use Translate which by default uses the local space of the moved object
if (gameObject.CompareTag("1Team"))
{
unitGO.transform.Translate(Vector3.right * movementSpeed * Time.deltaTime);
}
else if (gameObject.CompareTag("2Team"))
{
unitGO.transform.Translate(Vector3.left * movementSpeed * Time.deltaTime);
// Same as
//unitGO.transform.Translate(-Vector3.right * movementSpeed * Time.deltaTime);
}
In general rather use CompareTag instead of == to throw an error if there is a typo
I have a third-person code, but the camera stutters when I walk backwards! Does anyone have a solution? The camera is separate from the player, the player rotates according to the view of the camera.
PlayerController.cs
if (Input.GetKey (KeyCode.LeftShift)) {
if(Input.GetKey(KeyCode.W) || Input.GetAxis ("Vertical") > 0) moveDirection += camera.forward;
if(Input.GetKey(KeyCode.S) || Input.GetAxis ("Vertical") < 0) moveDirection += -camera.forward;
if(Input.GetKey(KeyCode.A) || Input.GetAxis ("Horizontal") < 0) moveDirection += -camera.right;
if(Input.GetKey(KeyCode.D) || Input.GetAxis ("Horizontal") > 0) moveDirection += camera.right;
if (Input.GetAxis ("Horizontal") != 0 || Input.GetAxis ("Vertical") != 0) {
//Multiply it by speed.
moveDirection.Normalize ();
moveDirection *= run;
//Applying gravity to the controller
moveDirection.y -= gravity * Time.deltaTime;
//Making the character move
controller.Move (moveDirection * Time.deltaTime);
}
moveDirection.y = 0f;
if (moveDirection != Vector3.zero) {
transform.rotation = Quaternion.RotateTowards (transform.rotation, Quaternion.LookRotation (moveDirection), rotationSpeed * Time.deltaTime);
}
}
Camera.cs
// Update is called once per frame
void Update () {
// We setup the rotation of the sticks here
float inputX = Input.GetAxis ("RightStickHorizontal");
float inputZ = Input.GetAxis ("RightStickVertical");
mouseX = Input.GetAxis ("Mouse X");
mouseY = Input.GetAxis ("Mouse Y");
finalInputX = inputX + mouseX;
finalInputZ = inputZ - mouseY;
rotY += finalInputX * inputSensitivity * Time.deltaTime;
rotX += finalInputZ * inputSensitivity * Time.deltaTime;
rotX = Mathf.Clamp (rotX, -clampAngle, clampAngle);
Quaternion localRotation = Quaternion.Euler (rotX, rotY, 0.0f);
transform.rotation = localRotation;
void LateUpdate () {
CameraUpdater ();
}
void CameraUpdater() {
Transform target = CameraFollowObj.transform;
// set the target object to follow
//move towards the game object that is the target
float step = CameraMoveSpeed * Time.fixedDeltaTime;
transform.position = Vector3.MoveTowards (transform.position, CameraFollowObj.transform.position, step);
}
In my experience when you have a smooth camera that stutters, it's because the camera - once it has gotten up to speed - moves faster than the object it is following:
Problem
Object moves
Camera starts to slowly move towards object
It catches up and stops
Camera to slowly start move towards object
Repeat 2-4; stuttery behaviour
Solution
Simple; tweak the camera speed variables to make sure it never completely catches up when the object is moving, but rather stays just behind so it doesn't have to stop every few frames.
Bonus reading material
Other sources will often explain their solution is to incorrectly put the code in FixedUpdate to miraculously get rid off the stuttery behaviour. Sometimes getting the correct behaviour from doing this is due to a series of things:
Update runs every frame update, so the time step (Time.deltaTime) here depends on machine but on my machine it will be, on average, every 0.007 seconds.
FixedUpdate runs on a fixed timestep, standard is 0.002 but can be changed in settings.
The code: float step = CameraMoveSpeed * Time.deltaTime;
Let's assume that CameraMoveSpeed is 1, for the sake of simple maths.
So with these numbers we can understand that putting the code in Update gives the following result
Update
Every 0.007 seconds, we update the camera lerp tick with CameraMoveSpeed * 0.007
FixedUpdate
Every 0.02 seconds, we update the camera lerp tick with CameraMoveSpeed * 0.007
Result
They move the same length every tick, but the ticks are less frequent in the FixedUpdate, which results in a slower camera smoothing and thus, "solves" the issue described as answer to this post of, in a way, tweaking camera speed variables to get a slower camera follow but instead of tweaking variables you havev moved your code to the physics update instead of the frame update and you only solved the issue by accident, without understanding the cause.
I am starting a new unity3d project and i want to know how to rotate moving forward spaceship from y-axis to left and right.
void Update(){
transform.position += transform.forward * Time.deltaTime * 10f;
if(input.Getkey(KeyCode.LeftArrow))
{
//code for rotate ;
}
}
I want that when I press arrow left key then spaceship rotates from y-axis to left until the arrow key released.
You can use Transform.Rotate(Vector3).
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow))
transform.Rotate(transform.forward * 3);
if (Input.GetKey(KeyCode.RightArrow))
transform.Rotate(transform.forward * -3);
}
I dont really know if i understand the question, but I think this may help you.
void Update () {
if (Input.GetKeyDown (KeyCode.Space)){
transform.Rotate (new Vector3(Time.deltaTime * 0, 1, 0));
}
where the first 0 is for x-axis, number 1 is for y-axis and the other 0 is for z-axis
You'll want declare the speed and rotation speed as floats so you can easily change them later, but here you go. I did both left and right.
float speed = 10.0f;
float rotateSpeed = 2.0f;
void Update(){
transform.position += transform.forward * Time.deltaTime * speed;
if(Input.GetKeyDown(KeyCode.LeftArrow))
{
//code for rotate
transform.Rotate(vector3.left * Time.deltaTime * rotateSpeed);
}
else if(Input.GetKeyDown(KeyCode.RightArrow))
{
transform.Rotate(vector3.right * Time.deltaTime * rotateSpeed);
}
}
If you want to rotate the ship relative to the world then use:
transform.Rotate(vector3.left * Time.deltaTime * rotateSpeed, Space.World);
This code is attached to a camera:
transform.position += Input.GetAxis("Vertical") * transform.forward * mod;
transform.position += Input.GetAxis("Horizontal") * transform.right * mod;
I've used .forward and .right because the player is able to rotate the camera on the Y axiz, thus no matter which way the camera is facing the forward key will always move the camera relatively forward, the left key will move it relatively left and so on. Just to clarify - I want it to move in local space, not world space so forward is the direction it's facing, not necessarily Vector3(0,0,1).
The camera is free roaming and has no parent or target to follow.
The problem is the camera has an X rotation of 45 to look down. Using transform.forward will thus modify it's height. There is also some scroll code to change the cameras height so I don't want to set the hight to a fixed value. How can I limit the movement to X and Z only, preferably without parenting it it an empty?
Update: this code works but it's not pretty, I'm sure there is a more elegant solution using Vector3.Project, as xyLe_ is suggesting. If I figure it out I'll add to his answer.
mod = Time.deltaTime * 30;
float yPos = transform.position.y;
pos = transform.position;
pos += Input.GetAxis("Vertical") * transform.forward * mod;
pos.y = yPos;
pos += Input.GetAxis("Horizontal") * transform.right * mod;
pos += Input.GetAxis("Mouse ScrollWheel") * transform.up * mod * -30;
I might talk nonsense right now, but it seems pretty simple to me:
Vector3 desiredDirection = Vector3.Normalize(new Vector3(transform.forward.x, transform.position.y, transform.forward.z))
Just project transform.forward onto the x-z plane that is settled at the height of transform.position.y. Doing this (usually) results in a slightly shorter vector, so you have to renormalize it.
To visualize:
If I understand you correctly, transform.forward corresponds to the black vector and you want to have the green vector. By setting the y component of the black vector to the y component of the red dots positions y component, you get the purple vector, which has to be renormalized.
Even though this has been solved, the solution below should help other people having this problem.
Here is is a proper way to move toward transform.forward while ignoring its rotation:
1.Get the transform.forward.
2.Convert it to Local Space with InverseTransformDirection
3.Set the y axis to 0;
4.Normalize it with dir.Normalize();
5.Append the new pos to transform.position.
public float mod = 2;
void Update()
{
//Get Forward face
Vector3 dir = transform.forward;
//Convert to local Space
dir = transform.InverseTransformDirection(dir);
//Reset/Ignore y axis
dir.y = 0;
dir.Normalize();
//Append the new pos to the `transform.position`.
transform.position += dir * Input.GetAxis("Vertical") * mod;
transform.position += Input.GetAxis("Horizontal") * transform.right * mod;
}
Another Method(Not Recommended):
Since the camera is tilted to 45 angle:
1.Rotate it to -45
2.Move the camera normally
3.Rotate it back to 45
public float startingOffset = 45;
public float mod = 2;
// Update is called once per frame
void Update()
{
//Rotate it to -45
transform.Rotate(new Vector3(-startingOffset, 0, 0));
// Move the camera normally
transform.position += Input.GetAxis("Vertical") * transform.forward * mod;
transform.position += Input.GetAxis("Horizontal") * transform.right * mod;
//Rotate it back to 45
transform.Rotate(new Vector3(startingOffset, 0, 0));
}
Both these should work but the preferred way should be the first one.