I am having some issues with creating a script that once the player clicks upon a gameObject that gameObject will follow the mouse. The object will be dropped once the mouse is clicked again.
Here is the script:
public float distance = 10;
public void OnMouseDrag()
{
Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance);
Vector3 objPosition = Camera.main.ScreenToWorldPoint(mousePosition);
transform.position = objPosition;
}
This works fine, but the issue is if the player (the main cam) has any sort of movement script upon it such as this Character controller script on it or its parent, then the gameObject that is picked up will move around as if it is trying to get away from the mouse.
public float speed = 6.0f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
private Vector3 moveDirection = Vector3.zero;
void Update()
{
CharacterController controller = GetComponent<CharacterController>();
if(Input.GetKey(KeyCode.LeftShift))
{
speed = 15.0f;
}else
{
speed = 6.0f;
}
if(controller.isGrounded)
{
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
}
if(Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
float rotateRight = Input.GetAxis("Mouse X");
transform.Rotate(0, rotateRight, 0);
}
If the above script is disabled, then the GameObject does not freak out and it works fine.
I know that the input being made in the character controller is effecting the top script in some way, the mouse moving so the gameObject transforms in that direction while trying to keep to a certain point on the mouse.
But how to I make so it won't effect it.
I bet the mouse dragging is happening before your movement.
Try putting your dragging logic in LateUpdate() so it can accommidate for the new position
Related
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...
This is my movement script
[SerializeField]
Vector3 movement;
[SerializeField]
KeyCode Up;
[SerializeField]
KeyCode Down;
public Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
if (Input.GetKey(Up))
{
rb.velocity += movement;
}
if (Input.GetKey(Down))
{
rb.velocity -= movement;
}
}
And This is my camera script
[SerializeField]
Transform transTarget;
[SerializeField]
float speed;
void Update()
{
transform.position = transTarget.position;
float h = speed * Input.GetAxis("Mouse X");
transform.Rotate(0, h, 0);
}
Basically, if I turn 180 with the camera and then press the up arrow to go forward, my player goes backward. I want to fix that.
You don't have to create 2 separate codes to create a first-person controller, that is what I think you are trying to do. You only have to do one that goes to the player. The camera has to be the child of the player and be inside of it. You have to tell the player that when you press Up or Down they have to move in that direction, First, you have to detect if the player is pressing up or down, with the function: Input.GetAxis("Horizontal") will give 1 when the Up is pressed and -1 when the Down is pressed and 0 if anything else is pressed. After that, you have to tell him witch id to go: transform.formward, in front of him, and multiply by the velocity you want.
[SerializeField]
Vector3 movement;
[SerializeField]
KeyCode Up;
[SerializeField]
KeyCode Down;
public Rigidbody rb;
public float Sensibility, Speed;
private void Start()
{
rb = GetComponent<Rigidbody>();
Cursor.lockState = CursorLockMode.Locked;
Speed = 100;
Sensibility = 100;
}
void FixedUpdate()
{
float h = Sensibility * Input.GetAxis("Mouse X") * Time.deltaTime;
transform.Rotate(Vector3.up * h);
rb.velocity = Input.GetAxis("Vertical") * Speed * transform.forward * Time.deltaTime;
}
But this is a very basic movement I recommend this video to learn more: https://www.youtube.com/watch?v=_QajrabyTJc.
Good day everyone!
I was trying to make my player face the direction he's walking towards, but then weird things started happening. Whenever I now let go of my input keys, the player slowly gets sucked to his local z-axis. Sometimes he does this while standing up, sometimes he does this flipped.
Any help would be highly appreciated!
Thanks in advance!
I'll provide you with my script:
public class JackMovement3D : MonoBehaviour {
public float speed = 6.0F;
public float VerticalSpeed = 10f;
public float HorizontalSpeed = 60f;
public float rotationSpeed = 5f;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
private Animator animator;
private void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
CharacterController controller = GetComponent<CharacterController>();
// is the controller on the ground?
if (controller.isGrounded)
{
float horizontal = Input.GetAxis("Horizontal") * HorizontalSpeed;
float vertical = Input.GetAxis("Vertical") * VerticalSpeed;
//Feed moveDirection with input.
moveDirection = new Vector3(horizontal, 0, vertical);
moveDirection = transform.TransformDirection(moveDirection);
//Multiply it by speed.
moveDirection *= speed;
}
//Applying gravity to the controller
moveDirection.y -= gravity * Time.deltaTime;
animator.SetFloat("Blend", controller.velocity.magnitude);
//Look at walking direction
Quaternion newRotation = Quaternion.LookRotation(moveDirection);
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, rotationSpeed);
// CharacterController.Move to move the player in target direction
controller.Move(moveDirection * Time.deltaTime);
}
private void LateUpdate()
{
transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, transform.localEulerAngles.z);
}
}
Not sure if this is the issue you describe but it might be related to
Quaternion.LookRotation(moveDirection);
since if there is no Input the moveDirection is a Vector3(0,0,0) and Quaternion.LookRotation
Returns identity if forward or upwards magnitude is zero.
so you could probably avoid that resetting the rotation to idendity by adding a check like
// if movement is 0 do nothing else
if(Mathf.Approximately(moveDirection.sqrMagnitude, 0)) return;
this should be before adding the gravity.
Actually not sure again but I guess the gravity should be added after
void Update()
{
CharacterController controller = GetComponent<CharacterController>();
// is the controller on the ground?
if (controller.isGrounded)
{
float horizontal = Input.GetAxis("Horizontal") * HorizontalSpeed;
float vertical = Input.GetAxis("Vertical") * VerticalSpeed;
//Feed moveDirection with input.
moveDirection = new Vector3(horizontal, 0, vertical);
moveDirection = transform.TransformDirection(moveDirection);
//Multiply it by speed.
moveDirection *= speed;
}
animator.SetFloat("Blend", controller.velocity.magnitude);
// if movement is 0 do nothing else
if(Mathf.Approximately(moveDirection.sqrMagnitude, 0))
{
return;
}
moveDirection.y -= gravity * Time.deltaTime;
//Look at walking direction
var newRotation = Quaternion.LookRotation(moveDirection);
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, rotationSpeed);
// CharacterController.Move to move the player in target direction
controller.Move(moveDirection * Time.deltaTime);
}
I have a problem where the player moves in the direction but the animation of the charcter stays the same. So if i click "w" key the player runs forward the animation works. But when i click "s" for backwards the character does not rotate around to the direction it just moves/slides back with the character facing forward and no animation. Please help!!
public class Player : MonoBehaviour {
private Animator anim;
private CharacterController controller;
public float speed = 600.0f;
public float turnSpeed = 400.0f;
private Vector3 moveDirection = Vector3.zero;
public float gravity = 20.0f;
private Vector3 curLoc;
void Start () {
controller = GetComponent <CharacterController>();
anim = gameObject.GetComponentInChildren<Animator>();
}
void Update (){
if (Input.GetKey ("w")) {
anim.SetInteger ("AnimationPar", 1);
} else {
anim.SetInteger ("AnimationPar", 0);
}
if (Input.GetKey("s"))
{
anim.SetInteger("Condition", 1);
}
else
{
anim.SetInteger("Condition", 0);
}
if (controller.isGrounded){
moveDirection = transform.forward * Input.GetAxis("Vertical") * speed;
}
float turn = Input.GetAxis("Horizontal");
transform.Rotate(0, turn * turnSpeed * Time.deltaTime, 0);
controller.Move(moveDirection * Time.deltaTime);
moveDirection.y -= gravity * Time.deltaTime;
if (Input.GetKey(KeyCode.S))
{
}
}
}
You need to show Animator, how animations are playing and transitioning. Just open animator when game is playing and check if animation is playing where "Condition" parameter is passes. Check the animation transitions too. Also, I'd suggest you to change value "AnimationPar" to 0 when "s" is pressed.
if (Input.GetKey("s"))
{
anim.SetInteger ("AnimationPar", 0);
anim.SetInteger("Condition", 1);
}
i have a character controller which jumps but while jumping i want to change the x position of the character so basically he can turn while jumping, this is my attempt so far
//start of character controller
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded) {
//get the player vector movement vector
movePlayer = new Vector3(Input.acceleration.x,0,1);
//float h = Input.acceleration.x;
//translate the players movement
transform.Translate(movePlayer * moveSpeed * Time.deltaTime);
//the run animation
animation.CrossFade("run");
//restrict the movement of x-axis for player
Vector3 pos = transform.position;
pos.x = Mathf.Clamp(pos.x, -3.0f, 3.0f);
transform.position = pos;
if (Input.GetButton("Jump")){
//my ptoblem is here, the x axis on the vector3 is not happening
movePlayer =transform.TransformDirection(new Vector3(Input.acceleration.x,jumpSpeed,forwardJumpSpeed));
}
}
// attach the gravity and move controller
movePlayer.y -= gravity * Time.deltaTime;
controller.Move(movePlayer * Time.deltaTime);
current code:
void Update() {
CharacterController controller = GetComponent<CharacterController>();
//get the player vector movement vector
movePlayer = new Vector3(Input.GetAxis("Horizontal"),0,1);
//float h = Input.acceleration.x;
//translate the players movement
transform.Translate(movePlayer * moveSpeed * Time.deltaTime);
//the run animation
animation.CrossFade("run");
//restrict the movement of x-axis for player
Vector3 pos = transform.position;
pos.x = Mathf.Clamp(pos.x, -3.0f, 3.0f);
transform.position = pos;
if (controller.isGrounded) {
if (Input.GetButton("Jump")){
movePlayer =transform.TransformDirection(new Vector3(Input.acceleration.x,jumpSpeed,forwardJumpSpeed));
}
}
movePlayer.y -= gravity * Time.deltaTime;
controller.Move(movePlayer * Time.deltaTime);
this is my current code, the jump if statement is inside the if(controller.isGrounded) the character still moves but when i press spacebar it deosnt jump anymore.
When the player jumps its no longer grounded so any code under the if(controller.isGrounded) is not called. Put your movement code outside it but keep the jumping code inside it and it'll work fine.
// movement code goes here
// Keep the jumping code inside this if-statement
if (controller.isGrounded) {
if (Input.GetButton("Jump")){
movePlayer =transform.TransformDirection(new Vector3(Input.acceleration.x,jumpSpeed,forwardJumpSpeed));
}