I want my player not to rotate anymore after the game starts. I freeze rotation in the script and in the constraints too , but the player still rotates when it moves forward . What can I do ? ( I have a fps , and a character controller) . I also have a canvas with buttons to control left , right ? Should I put the rigibody or player script inside the Character object ( I made a player game object that contains the character and the camera)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Player : MonoBehaviour
{
public float playerSpeed = 1500;
public float directionalSpeed = 20;
private Rigidbody rb;
// Start is called before the first frame update
void Start()
{
GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeRotation;
}
// Update is called once per frame
void Update()
{
#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_WEBPLAYER
float moveHorizontal = Input.GetAxis("Horizontal");
transform.position = Vector3.Lerp(gameObject.transform.position, new Vector3(Mathf.Clamp(gameObject.transform.position.x + moveHorizontal, -2.5f, 2.5f), gameObject.transform.position.y, gameObject.transform.position.z), directionalSpeed * Time.deltaTime);
#endif
GetComponent<Rigidbody>().velocity = Vector3.forward * playerSpeed * Time.deltaTime;
transform.Rotate(Vector3.right * GetComponent<Rigidbody>().velocity.z / 3);
//MOBILE CONTROLS
Vector2 touch = Camera.main.ScreenToWorldPoint(Input.mousePosition + new Vector3(0, 0, 10f));
if (Input.touchCount > 0)
{
transform.position = new Vector3(touch.x, transform.position.y, transform.position.z);
}
}
public void MoveLeft()
{
rb.velocity = new Vector2(-playerSpeed, rb.velocity.y);
}
public void MoveRight ()
{
rb.velocity = new Vector2(playerSpeed, rb.velocity.y);
}
public void StopMoving()
{
rb.velocity = new Vector2(0f, rb.velocity.y);
}
void DetectInput()
{
float x = Input.GetAxisRaw("Horizontal");
if (x > 0 )
{
MoveRight();
}
else if ( x < 0)
{
MoveLeft();
}
else
{
StopMoving();
}
}
}
If you added a rigidbody you can freeze the position or rotation
(no matter if rigidbody is 2d or no)
For first you have to declare the rigidbody
rb = GetComponent<Rigidbody>();
And then you can freeze your rotation RigidbodyConstraints (the selected label in the screenshot)
rigidbody.constraints = RigidbodyConstraints.FreezeRotationX;
//freeze only one rotation
rigidbody.constraints = RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezePositionY;
//freeze all rotations
to uncheck just type
rigidbody.constraints = RigidbodyConstraints.None;
If your game is 2d just add 2d to all Rigidbodies texts
Rotate using MoveRotation
Using the Rigidbody component constraints will only constrain the game object through the physics engine. You are currently rotating the transform manually.
From documentation:
void FixedUpdate()
{
Quaternion deltaRotation = Quaternion.Euler(m_EulerAngleVelocity * Time.deltaTime);
m_Rigidbody.MoveRotation(m_Rigidbody.rotation * deltaRotation);
}
Related
So i was trying 3rd character movement in unity an got stuck in here. The player animation is moving in loop but player is moving ahead of camera and than coming back, its doing it every cycle.
Let me provide char_control code and video link.
video link - https://drive.google.com/file/d/15VEIcOqy7yhQfACT4Pjxh-BZoVsrYdFS/view?usp=sharing
code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class char_control : MonoBehaviour
{
public GameObject Player;
//variable - type of variable
public bool isRunning;
public float horizontal_move;
public float vertical_move;
// Update is called once per frame
void Update()
{
if (Input.GetButton("Horizontal") || Input.GetButton("Vertical"))
{
Player.GetComponent<Animation>().Play("Running");
horizontal_move = Input.GetAxis("Horizontal") * Time.deltaTime * 100;
vertical_move = Input.GetAxis("Vertical") * Time.deltaTime * 1;
isRunning = true;
transform.Rotate(0, horizontal_move, 0);
transform.Translate(0, 0, vertical_move);
}
else
{
Player.GetComponent<Animation>().Play("Idle");
isRunning = false;
}
}
}
You should use Animator and Animator Controller for your purpose. To fix your problem you could probably disable root motion in your animation (Bake Into Pose on Root Transform Position (XZ), setting up Mask should work too) but still you will end up using Animator Controller so better do that asap
Have you checked that your "Running" animation has both "Loop Time" and "Loop Pose" checked. I know that the pose option is the one which makes my character act the way you described.
Use scripting to control character movement and movement animations:
[System.Serializable]
public class Anim//Game control animation
{
public AnimationClip idle;
public AnimationClip runForward;
public AnimationClip runBackward;
public AnimationClip runRight;
public AnimationClip runleft;
}
public class playermove : MonoBehaviour {
public float h = 0.0f;
public float v = 0.0f;
//assign the variable,
private Transform tr;
//move speed variable
public float movespeed = 10.0f;
//Rotate can use the Rotate function,
public float rotSpeed = 100.0f;
//The animation class variable to display to the inspector
public Anim anim;
//To access the variables of the following 3d model animation component objects
public Animation _animation;
// Use this for initialization
void Start () {
//Assign the Tr component to the initial part of the script
tr = GetComponent<Transform>();
// Find the anim component that is subordinate to itself and assign it to a variable.
_animation = GetComponentInChildren<Animation>();
_animation.clip = anim.idle;
_animation.Play();
}
// Update is called once per frame
void Update() {
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
Debug.Log("H=" + h.ToString());
Debug.Log("V="+ v.ToString());
//Calculate the moving direction vector of left, right, front and rear.
Vector3 moveDir = (Vector3.forward * v) + (Vector3.right * h);
//translate (movement direction *time.deltatime*movespeed, space.self)
tr.Translate(moveDir.normalized *Time.deltaTime*movespeed , Space.Self);
//vector3.up axis as the benchmark, rotate at rotspeed speed
tr.Rotate(Vector3.up * Time.deltaTime * rotSpeed * Input.GetAxis("Mouse X"));
if (v >= 0.1f)
{
//forward animation
_animation.CrossFade(anim.runForward.name, 0.3f);
}
else if (v <= -0.1f)
{
//back animation
_animation.CrossFade(anim.runBackward.name, 0.3f);
}
else if (h >= 0.1f)
{
//right animation
_animation.CrossFade(anim.runRight.name, 0.3f);
}
else if (h <= -0.1f)
{
//left animation
_animation.CrossFade(anim.runleft.name, 0.3f);
}
else
{
_animation.CrossFade(anim.idle.name, 0.3f);
}
//Based on the keyboard input value, execute the animation to be operated
}
}
hope it helps you.
I am trying to flip my character sprite when moving left in my game, and I have followed multiple tutorials however my sprite does not seem to flip. It is always facing the same way.
Below is my code for my character's movement. I have created a Flip() function and 2 if statements used to call the function. The character can move left, right, up and down (no jumping).
I cannot seem to see where an error would be and why it is not flipping, so any help would be appreciated. thank you.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
// Start is called before the first frame update
private Animator animate;
public float moveSpeed = 6f;
bool facingRight = true;
public Rigidbody2D rb;
Vector2 movement;
private void Start()
{
animate = gameObject.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
animate.SetFloat("Speed", Mathf.Abs(movement.x));
if(movement.x < 0 && facingRight)
{
Flip();
}
else if (movement.x > 0 && !facingRight)
{
Flip();
}
}
void FixedUpdate()
{
rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
}
void Flip()
{
Vector3 currentScale = gameObject.transform.localScale;
currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
facingRight = !facingRight;
}
}
Updated code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
// Start is called before the first frame update
private Animator animate;
public float moveSpeed = 6f;
bool facingRight = true;
public Rigidbody2D rb;
Vector2 movement;
private void Start()
{
animate = gameObject.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
animate.SetFloat("Speed", Mathf.Abs(movement.x));
if (movement.x < 0 && facingRight)
{
GetComponent<SpriteRenderer>().flipX = true;
}
else if (movement.x > 0 && !facingRight)
{
GetComponent<SpriteRenderer>().flipX = false;
}
}
void FixedUpdate()
{
rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
}
void Flip()
{
Vector3 currentScale = gameObject.transform.localScale;
currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
facingRight = !facingRight;
}
}
Try to set the flipX property of the SpriteRenderer.
GetComponent<SpriteRenderer>().flipX = true;
You have an animator attached to the game object, if the scale value is controlled by the animation clip, you cannot change it. A typical workaround is give the game object an empty parent and change its scale.
Player <---- Change scale here
Model <---- Animator here
transform.Rotate(0f, 180f, 0f); you have to change y while fliping
will work better instead of using currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
This code worked for me
private void Flip()
{
// Rotate the player
if (transform.localEulerAngles.y != 180 && !facingRight)
transform.Rotate(0f, 180f, 0f);
else if(transform.localEulerAngles.y != 0 && facingRight)
transform.Rotate(0f, -180f, 0f);
// player flip point of attck also flip is direction
//transform.Rotate(0f, 180f, 0f);
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
GetComponent<SpriteRenderer>().flipX = true;
isLookingRight = false;
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
GetComponent<SpriteRenderer>().flipX = false;
isLookingRight = true;
}
Going to right
Going to left
I am attempting to make 2D topdown shooter game. I first implemented weapon rotation and it worked fine. However, after implementing character sprite flip, the weapon sprite now doesn't rotate to right and the character sprite went weird. What am I doing wrong?
Character Movement Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public float speed;
private Rigidbody2D rb;
Vector2 movement;
bool facingRight = true;
// Update is called once per frame
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (mousePos.x > transform.position.x && facingRight)
{
flip();
}
else if (mousePos.x > transform.position.x && !facingRight)
{
flip();
}
}
void flip()
{
facingRight = !facingRight;
transform.Rotate(0f, 180f, 0f);
}
private void FixedUpdate()
{
movement.Normalize();
rb.velocity = new Vector2(movement.x * speed * Time.fixedDeltaTime, movement.y * speed * Time.fixedDeltaTime);
}
}
Weapon Rotation Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunRotation : MonoBehaviour
{
// Gun Rotation Function
public float offset;
private SpriteRenderer spriteRender;
// Start is called before the first frame update
void Start()
{
spriteRender = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void Update()
{
// Gun Rotation Function
Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
float rotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rotZ + offset);
if (rotZ < 89 && rotZ > -89)
{
Debug.Log("Facing right");
spriteRender.flipY = false;
}
else
{
Debug.Log("Facing left");
spriteRender.flipY = true;
}
}
}
You need just to reverse > in else if condition and it'll work fine
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (mousePos.x > transform.position.x && !facingRight)
{
flip();
}
else if (mousePos.x < transform.position.x && facingRight)
{
flip();
}
I am new to Unity so please be kind
So I want my character to move in the direction of the last key pressed. If I press W (up) and D (right) at the same time, the player will move in the direction of what came first. If I release that key and continue to hold the key that was pressed 2nd, the character doesn't change direction until you release said key and repress. This is ruining the feel of my game and I would like some help fixing this problem:)
Here is my character controller script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerController : MonoBehaviour
{
public float moveSpeed = 5f;
public Rigidbody2D rb;
public Animator anim;
Vector2 movement;
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal"); //gets axis as vector2
movement.y = Input.GetAxisRaw("Vertical");
anim.SetFloat("Horizontal", movement.x);
anim.SetFloat("Vertical", movement.y); //sets animation parameters
anim.SetFloat("Speed", movement.sqrMagnitude);
if (Input.GetAxisRaw("Horizontal") == 1 || Input.GetAxisRaw("Horizontal") == -1 || Input.GetAxisRaw("Vertical") == 1 || Input.GetAxisRaw("Vertical") == -1)
//If statement to set the correct idle animation (idle right, left, down) based off last direction.
{
anim.SetFloat("LastHorizontal", Input.GetAxisRaw("Horizontal"));
anim.SetFloat("LastVertical", Input.GetAxisRaw("Vertical"));
}
}
void FixedUpdate()
{
if (Mathf.Abs(movement.x) > Mathf.Abs(movement.y)) //if statement disables diagonal movement
{
movement.y = 0;
}
else
{
movement.x = 0;
}
rb.MovePosition(rb.position + movement.normalized * moveSpeed * Time.fixedDeltaTime); //applies movement to player
}
}
Instead of changing movement only on one axis in yout fixed update, I'd try forcing the direction vector for each key. So your code would look like this:
void FixedUpdate()
{
Vector3 movement = Vector3.zero
if (Input.GetKey(KeyCode.W))
{
movement.y = 1;
}
else if (Input.GetKey(KeyCode.S))
{
movement.y = -1;
}
else if (Input.GetKey(KeyCode.A))
{
movement.x = -1;
}
else if (Input.GetKey(KeyCode.D))
{
movement.x = 1;
}
else
{
movement = Vector3.zero
}
rb.MovePosition(rb.position + movement.normalized * moveSpeed * Time.fixedDeltaTime); //applies movement to player
}
The result of this should be your character not being able to move diagonaly
I have a Cube(player) and a Plane(floor) in my Scene. Both have Colliders attached to them and there is a RigidBody component attached only to the Cube. Cube is placed on the Plane.
LOGS
I don't understand why am I getting those last 3 values.(These too are values for dis value)
CODE
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class jump : MonoBehaviour {
private Rigidbody rb;
private float initialPos = 0.5f ;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update () {
//Debug.Log(rb.velocity.magnitude);
if (Input.GetKeyDown(KeyCode.Space))
{
rb.velocity = new Vector3(0f , 1f , 0f) * 10 ;
Debug.Log(rb.velocity);
}
if (rb.velocity.y > 0 && !Input.GetKey(KeyCode.Space))
{
float dis = rb.transform.position.y - initialPos;
Debug.Log(dis);
rb.velocity += new Vector3(0f, 1f, 0f) * Physics.gravity.y;
//Debug.Log(rb.velocity);
//Debug.Log("I am here");
//rb.velocity = Vector3.zero;
}
}
private void OnCollisionEnter(Collision collision)
{
rb.velocity = Vector3.zero;
Debug.Log(rb.velocity);
Debug.Log("...........................Collision " + gameObject.name);
}
}