Trying to create a 3rd person controller in Unity but the player is not moving - c#

This is what I have so far.
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
CharacterController control;
[SerializeField]
float moveSpeed = 5.0f;
[SerializeField]
float jumpSpeed = 20.0f;
[SerializeField]
float gravity = 1.0f;
float yVelocity = 0.0f;
// Use this for initialization
void Start () {
control = GetComponent<CharacterController> ();
}
// Update is called once per frame
void Update ()
{
Vector3 direction = new Vector3 (Input.GetAxis ("Horizontal"), 0, Input.GetAxis ("Vertical"));
Vector3 velocity = direction * moveSpeed;
if (control.isGrounded) {
if (Input.GetButtonDown ("Jump")) {
yVelocity += jumpSpeed;
}
} else {
yVelocity -= gravity;
}
velocity.y = yVelocity;
control.Move (velocity*Time.deltaTime);
}
}
I'm following a tutorial, and it looks like everything is the same, but the player is not moving.

If it is all same with tutorial, your problem must be about your input settings. Check your "Horizontal", "Vertical", "Jump" from Edit -> Project Settings -> Input
Then on inspector look at variables under Axis list to check them if they assigned true, maybe there is no Horizontal or Vertical variable.

Related

How to make my character look in the direction of the camera in Unity 3d?

My character has a chinemachine camera attached to it and it is moving perfectly fine. But when I move my mouse to change the camera direction it is not looking in that direction. And I can't figure out how to make it look in that direction.
I have a reference to the original camera at the top of the script by the name cam.
The script has different functions for movement, rotation, animation, etc.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//so that unity recognises the callbacks ctx passed to the movementinput
using UnityEngine.InputSystem;
public class AnimationAndMovController : MonoBehaviour
{
public Transform cam;
public float speed;
//here we are creadting three vars for the animation
//vector2 currentMovementInput stores the input axis of the player
//vector3 store the current position of the player
PlayerInput playerInput;
CharacterController characterController;
Animator animator;
Vector2 currentMovementInput;
Vector3 currentMovement;
Vector3 currentRunMovement;
Vector3 moveDir;
bool isMovementPressed;
bool isRunPressed;
float rotationFactor = 15.0f;
// float turnSmoothtime = 0.1f;
// float turnSmoothVelocity ;
float runMultiplier = 4.0f;
int walkHash ;
int runHash ;
//runs before start function
void Awake(){
playerInput = new PlayerInput();
characterController = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
// walkHash = Animator.StringToHash("Walking");
// runHash = Animator.StringToHash("run");
//now instead of writing the logic three times we pass the callback ctx to the movementInput() function
playerInput.CharacterControls.Move.started += movementInput;
playerInput.CharacterControls.Move.canceled += movementInput;
playerInput.CharacterControls.Move.performed += movementInput;
playerInput.CharacterControls.Run.started += handleRun;
playerInput.CharacterControls.Run.canceled += handleRun;
}
void handleRun(InputAction.CallbackContext ctx){
isRunPressed = ctx.ReadValueAsButton();
}
//we are going to handle rotations with quaternions
void handleRotation(){
Vector3 positionToLookAt;
positionToLookAt.x = currentMovement.x;
positionToLookAt.y = 0.0f ;
positionToLookAt.z = currentMovement.z;
Vector3 direction = new Vector3(positionToLookAt.x, 0.0f, positionToLookAt.z).normalized;
Quaternion currentRotation = transform.rotation;
//we take the current rotation and the target rotation and slerp them *FYI : Im still not sure how slerp works
if(isMovementPressed){
Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt);
transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactor * Time.deltaTime);
}
}
//we are passing the callback ctx to this function so that we dont have to call the function everytime we start, cancel or perform the movement
void movementInput(InputAction.CallbackContext ctx){
//we are setting the movement input to the axis of the player
currentMovementInput = ctx.ReadValue<Vector2>();
currentMovement.x = currentMovementInput.x;
//we are setting the z axis to the y axis of the player because we move y axis on keyboard or joystick but in game we move in z axis
currentMovement.z = currentMovementInput.y;
//now we are setting the run movement to the current movement
currentRunMovement.x = currentMovementInput.x * runMultiplier;
currentRunMovement.z = currentMovementInput.y * runMultiplier;
isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
}
void handleAnimation(){
bool walk = animator.GetBool("walking");
bool run = animator.GetBool("run");
if(isMovementPressed && !walk){
animator.SetBool("walking", true);
}
else if(!isMovementPressed && walk){
animator.SetBool("walking", false);
}
if((isMovementPressed && isRunPressed) && !run){
animator.SetBool("run", true);
}
else if((!isMovementPressed || !isRunPressed)&& run){
animator.SetBool("run", false);
}
}
void handleGravity(){
//we are setting the gravity to -9.8f because we are moving in y axis
if(characterController.isGrounded){
float groundGravity = -0.05f;
currentMovement.y = groundGravity;
currentRunMovement.y = groundGravity;
}
else{
float gravity = -9.8f;
currentMovement.y += gravity * Time.deltaTime;
currentRunMovement.y += gravity * Time.deltaTime;
}
}
// Update is called once per frame
void Update()
{
handleAnimation();
handleRotation();
handleGravity();
if(isRunPressed){
characterController.Move(currentRunMovement * Time.deltaTime);
}
else{
characterController.Move(currentMovement * Time.deltaTime);
}
}
//we are checking if the player script gets enabled or disabled and accordingly we are enabling or disabling the player input
void OnEnable(){
playerInput.CharacterControls.Enable();
}
void OnDisable(){
playerInput.CharacterControls.Disable();
}
}
That quite a lot of code to dive into.
I'd try:
Quaternion cameraRot = Camera.Main.transform.rotation;
transform.rotation = cameraRot;
Or if you have a target Quaternion.LookRotation:
Vector3 relativePos = target.position - transform.position;
// the second argument, upwards, defaults to Vector3.up
Quaternion rotation = Quaternion.LookRotation(relativePos, Vector3.up);
transform.rotation = rotation;
Hope that helps
Use Transform.LookAt, which points a Game Object's rotation towards a target's position.
In your case, this would be
transform.LookAt(cam);
here is the code that I use..
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCamera : MonoBehaviour
{
public float sensitivity = 1000f;
public float xRotation = 0f;
public Transform playerBody;
public Quaternion localRotate;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
float MX = Input.GetAxis("Mouse X")*sensitivity*Time.deltaTime;
float MY = Input.GetAxis("Mouse Y")*sensitivity*Time.deltaTime;
xRotation -= MY;
xRotation = Mathf.Clamp(xRotation,-90f,90f);
transform.localRotation = Quaternion.Euler(xRotation,0f,0f);
localRotate = transform.localRotation;
playerBody.Rotate(Vector3.up * MX);
}
}
the player body you see is the player object to you character...
note that the camera is use is not In. cinema chine and is inside of the player...

Unity mouse y-axis locked only in build

I have a mouse look script which allows the player to look up and down in a 3D first person game. It works perfectly in the Unity Editor. Once I build the game, I can only move the mouse on x-axis. I have tried using the old and new input system, but the same result happens. I have tried setting the window mode in the player settings to fullscreen and windowed already as well as setting the input system to both.
Here is a video clip of this happening: https://www.youtube.com/watch?v=_AxX2OmkU_Y
public class MouseLook : MonoBehaviour
{
Transform playerTransform;
PlayerController playerController;
InputMaster input;
Vector2 lookDir;
public float sens = 500f;
private float xRotation;
// Start is called before the first frame update
void Start()
{
// Hide cursor
Cursor.lockState = CursorLockMode.Locked;
playerTransform = transform.parent;
playerController = playerTransform.GetComponent<PlayerController>();
input = playerController.Input;
}
// Update is called once per frame
void Update()
{
lookDir = input.Player.Look.ReadValue<Vector2>();
// Gets mouse inputs
float moveX = lookDir.x * sens * Time.deltaTime;
float moveY = lookDir.y * sens * Time.deltaTime;
// Clamps rotation
xRotation -= moveY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
playerTransform.Rotate(Vector3.up * moveX);
}
}
I would use Input.GetAxis("MouseX") and Input.GetAxis("MouseY")
Make sure not to use Input.GetAxisRaw because it won't work as intended with mouse inputs :)
Documentation Link
Here is a example from the above link for mouse looking:
using UnityEngine;
using System.Collections;
// Performs a mouse look.
public class ExampleClass : MonoBehaviour
{
float horizontalSpeed = 2.0f;
float verticalSpeed = 2.0f;
void Update()
{
// Get the mouse delta. This is not in the range -1...1
float h = horizontalSpeed * Input.GetAxis("Mouse X");
float v = verticalSpeed * Input.GetAxis("Mouse Y");
transform.Rotate(v, h, 0);
}
}

Unity Animator component unnecessarily overriding scripted position of Game Objects

I have a hand and pistol(fps) gameObject. and the recoil system is controlled directly from script (including the slide on the pistol) and it works perfectly.
the moment I added an idle and reload animation the pistol slider stops moving back when recoiling.
When I disable the animator component it works back fine, I even deleted all my keyframes on the "idle" animation still the slider doesn't work.
I have my Recoil Script below
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponRecoil : MonoBehaviour
{
[SerializeField]
private float recoilX;
[SerializeField]
private float recoilY;
[SerializeField]
private float recoilZ;
[SerializeField]
private float recoilResetSpeed = 0.8f;
[SerializeField]
private float snappiness = 2f;
public Transform parent;
Vector3 targetRotation;
Vector3 currentRotation;
Vector3 targetHandPosition;
Vector3 currentHandPosition;
[SerializeField]
private List<EjectorData> bulletEjectors;
[SerializeField]
float ejectorBackDistance;
[SerializeField]
float ejectorReturnSpeed=10;
void Start() {
foreach (EjectorData ejector in bulletEjectors)
{
ejector.startPosition = ejector.obj.localPosition;
}
}
void Update()
{
coolDownWeaponRecoilEffect();
}
void coolDownWeaponRecoilEffect()
{
targetRotation = Vector3.Lerp(targetRotation, Vector3.zero, recoilResetSpeed * Time.deltaTime);
currentRotation = Vector3.Slerp(currentRotation, targetRotation, snappiness * Time.deltaTime);
//resetting the pushback effect of the recoil of the hand
targetHandPosition = Vector3.Lerp(targetHandPosition, Vector3.zero, recoilResetSpeed * Time.deltaTime);
currentHandPosition = Vector3.Slerp(currentHandPosition, targetHandPosition, snappiness * Time.deltaTime);
if (parent == null) return;
parent.localRotation = Quaternion.Euler(currentRotation);
transform.localPosition = currentHandPosition;
//resseting the bullet ejectors back to their normal positions
foreach (EjectorData ejector in bulletEjectors)
{
ejector.obj.localPosition = Vector3.Lerp(ejector.obj.localPosition, ejector.startPosition, ejectorReturnSpeed * Time.deltaTime);
}
}
public void Recoil() {
targetRotation += new Vector3(recoilX, Random.Range(-recoilY, recoilY), 0);
targetHandPosition -= new Vector3(0, 0, recoilZ);
foreach (EjectorData ejector in bulletEjectors) {
ejector.obj.localPosition -= new Vector3(0, 0, ejectorBackDistance);
}
}
[System.Serializable]
class EjectorData {
public Transform obj;
public Vector3 startPosition;
}
}
To put is simply your script is overriding the position of the bones, and the animator is overriding that; rendering it useless
To change the bones rotation/Position on top the animation you should look into Unity's Animation Rigging
AnimationRigging works as a post-process step of the Animator and has the same restrictions as any animated hierarchy. you can use the Override Transform Constraint To achieve the effect you are looking for.
this tutorial might help you a bit if you are stuck.

transform.position doesn't move player

I have a Player (made out of an cylinder, some FirstCam, SecondCam and ThirdCam, for switching views when pressing a certain key - doesn't matter), which is located on a cube (wide enough to take a walk on it). There's nothing else below the cube.
This is how it looks like:
This is the Player's structure:
This is the inspector for Player:
I have the following script ResetToInitial.cs, attached to my Player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResetToInitial : MonoBehaviour {
Vector3 pos;
void Start() {
pos = transform.position;
}
void Update() {
if (transform.position.y < -10) {
transform.position = pos;
}
}
}
and also some movement script PlayerMovement.cs that allows him to move up, down, left, right, jump and sprint.
This is PlayerMovement.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PlayerMovement : MonoBehaviour {
public CharacterController controller;
Vector3 velocity;
bool isGrounded;
public Transform groundCheck;
public LayerMask groundMask;
public TextMeshPro State;
public TextMeshPro State2;
public TextMeshPro State3;
// Start is called before the first frame update
void Start() {
}
// Update is called once per frame
void Update() {
float groundDistance = 0.4f;
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if (isGrounded && velocity.y < 0) {
velocity.y = -2f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
float g = -20f;
float jumpHeight = 1f;
float speed = 6f;
if (Input.GetKey(KeyCode.LeftShift)) {
speed = 8f;
State.text = "running mode";
State2.text = "running mode";
State3.text = "running mode";
} else {
speed = 5f;
State.text = "walking mode";
State2.text = "walking mode";
State3.text = "walking mode";
}
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
if (Input.GetButton("Jump") && isGrounded) {
velocity.y = Mathf.Sqrt(jumpHeight * -2f * g);
}
velocity.y += g * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
ResetToInitial.cs is intended to teleport the Player to the initial position (back on the cube, the position recorded when the scene loads), after he falls of the cube. The problem is transform.position won't move the player anywhere. It won't do anything. I tried to output something in the last if to see if it works, and the output was printed, but still no teleportation happened.
What could be the problem?

How to make my 2D character 'look' or flip in the direction he is moving?

I'm a total newbie in Unity and I'm learning/making my first game, which will be a platformer. I want to get the movement perfect first. I've added a simple script that enables the player to move and jump.
Here it is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour{
public float jumpspeed = 5f;
public float speed = 5f;
Rigidbody2D rb;
GameObject character;
// Start is called before the first frame update
void Start()
{
}
void Awake(){
rb = gameObject.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)){
Jump();
}
Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0f, 0f);
transform.position += move *Time.deltaTime * speed;
}
void Jump(){
rb.AddForce(new Vector2(0f, jumpspeed), ForceMode2D.Impulse);
}
}
Now, I want the character to face in the direction in which it moves. The png is facing to the right by default.
How can I do that? Also, can I make my movement script better?
Thanks in advance!
I typically do this using code like this based off a bool.
void FlipSprite()
{
isFacingRight = !isFacingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}

Categories