Hello again my friends.
I am trying to make a 3D game in Unity in which I am trying to move my character with simple WASD keys.
However, it is successful only from one direction. From the opposite direction the controls seem reversed. Even when I look around with the mouse. The game is considered to be a First-Person Shooter(FPS).
The Player code is:
[SerializeField]
private NavMeshAgent navMeshAgent;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
Vector3 direction = new Vector3(Input.GetAxis("Horizontal1"), 0, Input.GetAxis("Vertical1"));
Vector3 velocity = direction * speed;
velocity.y -= gravity;
velocity = transform.TransformDirection(velocity);
controller.Move(direction * Time.deltaTime);
transform.position = navMeshAgent.nextPosition;
}
What should I do? I would really appreciate your help.
Try this example to move your character use your own logic ofc and change what have to be changed
private float speed = 2.0f;
public GameObject character;
void Update () {
if (Input.GetKeyDown(d)){
transform.position += Vector3.right * speed * Time.deltaTime;
}
if (Input.GetKeyDown(a)){
transform.position += Vector3.left* speed * Time.deltaTime;
}
if (Input.GetKeyDown(w)){
transform.position += Vector3.forward * speed * Time.deltaTime;
}
if (Input.GetKeyDown(s)){
transform.position += Vector3.back* speed * Time.deltaTime;
}
}
Related
So I am making game and I need good PlayerMovement Script but there is little problem. You see I made so that my player is following this path (I didn't make it I downloaded it from marketplace) and he can go only forward. Then I put another Vector3 (horizontalMove) value and hooked it to transform.position and didn't get what I really wanted. When I hit play everything works and I can go Left to Right but my position does not stay the same. The moment I let go of my keys (a, d) my player returns to track, resets in middle. I need it to stay in the position I left him. And too, just adding rb.position in my transform.position just send me flying in the air. I need help.
`public class PathFollower : MonoBehaviour
{
public PathCreator pathCreator;
public EndOfPathInstruction endOfPathInstruction;
public float speed = 5;
float distanceTravelled;
float horizontalInput;
[SerializeField] float horizontalMultiplier = 2;
public Rigidbody rb;
void Start() {
if (pathCreator != null)
{
// Subscribed to the pathUpdated event so that we're notified if the path changes during the game
pathCreator.pathUpdated += OnPathChanged;
}
}
void Update()
{
if (pathCreator != null)
{
horizontalInput = Input.GetAxis("Horizontal");
Vector3 horizontalMove = transform.right * horizontalInput * speed * Time.fixedDeltaTime * horizontalMultiplier;
distanceTravelled += speed * Time.deltaTime;
Debug.Log();
transform.position = pathCreator.path.GetPointAtDistance(distanceTravelled, endOfPathInstruction) + new Vector3 (0,1,0) + horizontalMove;
transform.rotation = pathCreator.path.GetRotationAtDistance(distanceTravelled, endOfPathInstruction);
}
}
// If the path changes during the game, update the distance travelled so that the follower's position on the new path
// is as close as possible to its position on the old path
void OnPathChanged() {
distanceTravelled = pathCreator.path.GetClosestDistanceAlongPath(transform.position);
}
}
}`
You need a global variable that holds the value of horizontalMove, so it isn't reset in the update loop.
Vector3 horizontalMove;
void Update()
{
if (pathCreator != null)
{
horizontalInput = Input.GetAxis("Horizontal");
Vector3 horizontalMove += transform.right * horizontalInput * speed * Time.deltaTime * horizontalMultiplier;
distanceTravelled += speed * Time.deltaTime;
Debug.Log();
transform.position = pathCreator.path.GetPointAtDistance(distanceTravelled, endOfPathInstruction) + new Vector3 (0,1,0) + horizontalMove;
transform.rotation = pathCreator.path.GetRotationAtDistance(distanceTravelled, endOfPathInstruction);
}
}
I also took the liberty to change fixedDeltaTime to deltaTime, since that is the appropriate variable for an Update context.
So I'm making a top down shooting game and I want the bullets to align with the direction they are shot at.
I'm passing the direction when instancing the bullet(code bellow) and applying it on the Start event but it doesn't rotate. However it applies when i use it on the Update event indicating that the value is indeed passed but somehow the Start event isn't able to rotate the object. I also tried the OnEnable event and same thing, it seems inneficient to set the rotation in every Update event how can i fix it.
{
[SerializeField] private float speed = 1f;
public Vector3 direction = Vector3.forward;
private float distanceTravelled = 0f;
void Start()
{
transform.LookAt(direction);;
}
void Update()
{
transform.position += speed * Time.deltaTime * direction;
distanceTravelled += speed * Time.deltaTime;
if (distanceTravelled > range)
{
Destroy(gameObject);
}
}
}
I think i fixed it, if theres a better solution please tell me :)
I used Invoke fujnction, it seems to delay the rotation enough so it gets properly applied.
{
[SerializeField] private float speed = 1f;
public Vector3 direction = Vector3.forward;
private float distanceTravelled = 0f;
void Start()
{
Invoke(nameof(SetForwardVector), 0f);
}
void Update()
{
transform.position += speed * Time.deltaTime * direction;
distanceTravelled += speed * Time.deltaTime;
if (distanceTravelled > range)
{
Destroy(gameObject);
}
}
void SetForwardVector()
{
transform.LookAt(direction);
}
}
Im making movement for my camera in unity. The starting position for my camera is 0,0,0. When i press the W key the code i take the current position and multiply it by a movement speed and equal it to another vector 3 to then update the postion of the position of the camera. It works great but i cant understand why when i think about.
If my camera is initialised at 0,0,0 then why does transform.forward * movementSpeed not always eqaul 0?
This is the same for all directions i just used W as an example
Any help would be greatly appreciated as im new to unity. Thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMovement : MonoBehaviour
{
private Vector3 newPosition;
[SerializeField] private float movementSpeed;
[SerializeField] private float movementTime;
// Start is called before the first frame update
void Start()
{
newPosition = transform.position;
Debug.Log(transform.position); //prints 0.0,0.0,0.0
Debug.Log(transform.forward * movementSpeed); //prints 0.0,0.0,0.3
}
// Update is called once per frame
void Update()
{
handleKeyboardInput();
}
void handleKeyboardInput()
{
if (Input.GetKey(KeyCode.W))
{
newPosition += (transform.forward * movementSpeed);
}
if (Input.GetKey(KeyCode.A))
{
newPosition += (transform.right * -movementSpeed);
}
if (Input.GetKey(KeyCode.S))
{
newPosition += (transform.forward * -movementSpeed);
}
if (Input.GetKey(KeyCode.D))
{
newPosition += (transform.right * movementSpeed);
}
transform.position = Vector3.Lerp(transform.position, newPosition, Time.deltaTime * movementTime);
}
}
The reason your code works is becuase transform.forward and transform.right refer to the forward and right directions of you player. When you add transform.forward * speed to your newPosition, you are adding the forward direction of the player but with a magnitude (length) of your speed.
If you want to try to understand it better, you can use print(transform.forward) or print(transform.forward * speed) or do Debug.drawRay(transform.position, transform.forward)
Your code is multiplying transform.forward(0,0,1) or transform.right, both of them are not zero vectors, instead they represent the specified direction.
Vector3.forward is (0,0,1) if you want zero use Vector3.zero.
I use this code to move and rotate my object, but it moves through the walls. Yes, I have colliders on object and walls, but my object doesn't collide with these walls.
using UnityEngine;
using System.Collections;
public class player_Control : MonoBehaviour {
public float upspeed;
public float downspeed;
public float rotationSpeed;
Transform myTrans;
Vector3 myPos;
Vector3 myRot;
float angle;
void Start() {
myPos = transform.position;
myRot = transform.rotation.eulerAngles;
}
void FixedUpdate() {
angle = transform.eulerAngles.magnitude * Mathf.Deg2Rad;
if (Input.GetKey(KeyCode.RightArrow)) { // ROTATE RIGHT
myRot.z -= rotationSpeed;
}
if (Input.GetKey(KeyCode.LeftArrow)) { // ROTATE LEFT
myRot.z += rotationSpeed;
}
if (Input.GetKey(KeyCode.UpArrow)) { // UP
myPos.y += (Mathf.Cos(-angle) * upspeed) * Time.deltaTime;
myPos.x += (Mathf.Sin(-angle) * upspeed) * Time.deltaTime;
}
if (Input.GetKey(KeyCode.DownArrow)) { // DOWN
myPos.y += (Mathf.Cos(-angle) * -downspeed) * Time.deltaTime;
myPos.x += (Mathf.Sin(-angle) * -downspeed) * Time.deltaTime;
}
transform.position = myPos;
transform.rotation = Quaternion.Euler(myRot);
}
}
Your issue here is that you are bypassing the Unity's physics engine and altering the players position and rotation directly.
Unity's physics checks are built around usage of the Rigidbody component and has several specific functions for changing an objects position and rotation so that it collides correctly with other objects within the scene.
For your usage above I would look at the following two functions for changing position and rotation of your character:
https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html
https://docs.unity3d.com/ScriptReference/Rigidbody.MoveRotation.html
I'm trying to add jumping to the controls of our control script but it just doesn't work yet and I'm getting kind of frustrated because I tried a lot to make it work. I don't use rigidbodies and rather want to use script based physics and - but later - raycasts (to detect ground). It's 3D but with a fixed perspective because the characters are sprites (we are thinking about trying a style similar to Don't Starve, Paper Mario etc.). And the thing I want to put in for now is to jump upwards when the character stands still and later on jumps that also let the character travel a bit of distance when the character moves. Well, you get the picture. For that I first need to get jumping working at all - and also gravity to put the character back down while also considering that the character could land on a ground that has a different height than the starting ground.
What happens now is that the character jumps just a tiny little bit, like not even a hop, and then falls down endlessly - or goes up endlessly when jump is pressed again. So, how do I fix that?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Controls3D : MonoBehaviour
{
public float player3DSpeed = 5f;
private bool IsGrounded = true;
private const float groundY = (float) 0.4;
private Vector3 Velocity = Vector3.zero;
public Vector3 gravity = new Vector3(0, -10, 0);
void Start()
{
}
void Update()
{
if (IsGrounded)
{
if (Input.GetButtonDown("Jump"))
{
IsGrounded = false;
Velocity = new Vector3(Input.GetAxis("Horizontal"), 20, Input.GetAxis("Vertical"));
}
Velocity.x = Input.GetAxis("Horizontal");
Velocity.z = Input.GetAxis("Vertical");
if (Velocity.sqrMagnitude > 1)
Velocity.Normalize();
transform.position += Velocity * player3DSpeed * Time.deltaTime;
}
else
{
Velocity += gravity * Time.deltaTime;
Vector3 position = transform.position + Velocity * Time.deltaTime;
if (position.y < groundY)
{
position.y = groundY;
IsGrounded = true;
}
transform.position = position;
}
}
}
If i were you, i think i wouldve changed the whole thing into a character controller, as this simplifies the process, a ####ton :P
If you figure out you do want to use the CC. This is the solution i usually use:
CharacterController controller = GetComponent<CharacterController>();
// is the controller on the ground?
if (controller.isGrounded)
{
//Feed moveDirection with input.
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
//Multiply it by speed.
moveDirection *= speed;
//Jumping
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
//Applying gravity to the controller
moveDirection.y -= gravity * Time.deltaTime;
//Making the character move
controller.Move(moveDirection * Time.deltaTime);
moveDirection is a Vector3 Type variable, and speed and jumpSpeed are public float values used to modify the speed.
Please NOTE: Character Controllers, let you program your own Physics.