I am learning Unity Game development .. I was following https://unity3d.com/learn/tutorials/projects/survival-shooter/player-character?playlist=17144
Did everything same but,
I want the player object to rotate towards the mouse pointer. But it's not rotating towards mouse pointer..
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
Vector3 movement;
Animator anim;
Rigidbody playerRigidbody;
int floormask;
float camraylength = 100f;
float speed = 10f;
void Awake()
{
anim = GetComponent<Animator>();
floormask = LayerMask.GetMask("floor");
playerRigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
moving(h, v);
tunning();
animationz(h, v);
}
void moving(float h, float v)
{
movement = new Vector3(h, 0, v);
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition(transform.position + movement);
}
void tunning()
{
Ray camray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit floorhit;
if(Physics.Raycast(camray,out floorhit, camraylength, floormask))
{
Vector3 playertomouse = floorhit.point - transform.position;
playertomouse.y = 0f;
Quaternion newrotate = Quaternion.LookRotation(playertomouse);
playerRigidbody.MoveRotation(newrotate);
}
}
void animationz(float h, float v)
{
bool walking = h != 0f || v != 0f;
anim.SetBool("IsWalking", walking);
}
}
The tunning() method is in the above code
If anything more you want then please comment. Thank you for the help...
I suggest you check several stuff to find the source of the problem:
You need to make sure you are using a Quad not a Plane and that the correct face is upwards
Make sure the layer of the quad is "floor" (it's case sensitive)
Make sure the camera is not further than the 100f of the ray you are casting
And finally add a Debug.Log() inside the if condition to check if the ray hits the floor at all.
Related
I'm new to Unity and I'm trying to make it so the player can't jump while they're already jumping using IsGrounded which should check if they're on the ground, but instead if press space then IsGrounded true. It might be an issue within Unity itself but im not sure. Thanks!
The code:
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
float xInput, yInput;
[SerializeField] private LayerMask lm;
private Rigidbody2D rb;
private BoxCollider2D bc;
// Start is called before the first frame update
void Start()
{
}
private void Awake()
{
rb = transform.GetComponent<Rigidbody2D>();
bc = transform.GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void Update()
{
if (IsGrounded() && Input.GetKeyDown(KeyCode.Space))
{
float jumpVelocity = 25f;
rb.velocity = Vector2.up * jumpVelocity;
Debug.Log("IsGrounded");
}
xInput = Input.GetAxis("Horizontal");
transform.Translate(xInput * moveSpeed, 0, 0);
PlatformerMove();
}
void PlatformerMove()
{
rb.velocity = new Vector2(moveSpeed * xInput, rb.velocity.y);
}
private bool IsGrounded()
{
RaycastHit2D rc = Physics2D.BoxCast(bc.bounds.center, bc.bounds.size, 0f, Vector2.down * .1f, lm);
return rc.collider != null;
}
}```
You are using a
Physics2D.BoxCast(bc.bounds.center, bc.bounds.size, 0f, Vector2.down * .1f, lm);
Now if you look at the parameters of Physics2D.BoxCast
public static RaycastHit2D BoxCast(
Vector2 origin, Vector2 size,
float angle, Vector2 direction,
float distance = Mathf.Infinity,
int layerMask = Physics2D.AllLayers,
float minDepth = -Mathf.Infinity,
float maxDepth = Mathf.Infinity
);
You are passing in
origin = bc.bounds.center
size = bc.bounds.size
direction = Vector2.down (the magnitude doesn't matter for a distance!)
distance = lm (I think you note the issue now) => I suppose this is a layermask -> some rather big integer -> you shoot very far -> probably always hit the something
layerMask = Physics2D.AllLayers
In general, since it is a Boxcast this means you are shooting a box into space and check if on its way it is hitting something.
If that's intended you would rather pass in
RaycastHit2D rc = Physics2D.BoxCast(bc.bounds.center, bc.bounds.size, 0f, Vector2.down, 0.1f, lm);
Otherwise I suppose you rather would want to use Physics2D.OverlapBox instead which rather checks for an overlap in a fixed position/area without shooting it anywhere
RaycastHit2D rc = Physics2D.OverlapBox(bc.bounds.center, bc.bounds.size, 0f, lm);
I have a problem in keeping the character facing the same direction he was facing its always turn to the z direction of the world coordinate I hope to find way to fix this problem.
I tried to stop this with using Quaternion.LookRotation() and Vector3.RotateToward() but still when stop he rotate in idle animation to the world z direction.
public class MovementController : MonoBehaviour
{
Vector3 _CharacterDirection;
Quaternion _CharacterRotation=Quaternion.identity;
Animator _CharacterAnim;
Rigidbody _CharacterRigidbody;
public float TurnSpeed;
void Start()
{
_CharacterAnim = GetComponent<Animator>();
_CharacterRigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
CharacterMovement();
}
void CharacterMovement()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
_CharacterDirection.Set(h, 0, v);
_CharacterDirection.Normalize();
bool _IsHorizontalChange = !Mathf.Approximately(h, 0f);
bool _IsVerticalChange = !Mathf.Approximately(v, 0);
bool _IsWalking = _IsHorizontalChange || _IsVerticalChange;
_CharacterAnim.SetBool("IsWalking", _IsWalking);
Vector3 _DesairdForward = Vector3.RotateTowards(Vector3.forward, _CharacterDirection, TurnSpeed * Time.deltaTime, 0);
_CharacterRotation = Quaternion.LookRotation(_DesairdForward);
_CharacterRigidbody.MovePosition(_CharacterRigidbody.position + _CharacterDirection * Time.deltaTime);
_CharacterRigidbody.MoveRotation(_CharacterRotation);
}
}
In the Unity learn section - survival shooter, I am getting an error shows the following error
Type "UnityEngine.Animation" does not contain a definition for "SetBool" and no extension method "SetBool" of type "UnityEngine.Animation" could be found. Are you missing an assembly reference?
I have checked the name of files and components.
Code
using UnityEngine;
public class PlayerMovement: MonoBehaviour
{
public float speed = 6f;
Vector3 movement;
Animation anim;
Rigidbody playerRigidbody;
int floorMask;
float camRayLength = 100f;
void Awake()
{
floorMask = LayerMask.GetMask("Floor");
anim = GetComponent<Animation>();
playerRigidbody = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Verticle");
Move(h, v);
Turning();
Animating(h, v);
}
void Move(float h, float v)
{
movement.Set(h, 0f, v);
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition(transform.position + movement);
}
void Turning()
{
Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit floorHit;
if(Physics.Raycast (camRay ,out floorHit, camRayLength, floorMask))
{
Vector3 playerToMouse = floorHit.point - transform.position;
playerToMouse.y = 0f;
Quaternion newRotation = Quaternion.LookRotation(playerToMouse);
playerRigidbody.MoveRotation (newRotation);
}
}
void Animating(float h, float v)
{
bool walking = h!= 0f || v!= 0f;
anim.SetBool("IsWalking", walking);
}
}
The character's animation controller is of type Animator, not Animation. Use SetBool on Animator.
Animator anim;
void Awake()
{
// ...
anim = GetComponent<Animator>();
// ...
}
I'm trying to understand the code of the PlayerController made by Unity(Survival Shooter Tutorial).I understand everything, except the reason, why they wrote the difference between FLOOR-POINT(where the mouse is directed) and the player (transform position).I tried to write only the floor point without the player position and its worked.Why they wrote that? Maybe someone passed this tutorial and can help me with that?
Unity tutorial : https://unity3d.com/learn/tutorials/projects/survival-shooter/player-character?playlist=17144
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed= 6f;
Vector3 movement;
Animator anim;
Rigidbody playerRigidbody;
int floorMask;
float camRayLength=100f;
void Awake()
{
floorMask = LayerMask.GetMask("Floor");
anim = GetComponent<Animator> ();
playerRigidbody = GetComponent<Rigidbody> ();
}
void FixedUpdate()
{
float v = Input.GetAxisRaw ("Vertical");
float h = Input.GetAxisRaw ("Horizontal");
Move (h, v);
Turning ();
Animating(h,v);
}
void Move(float h,float v)
{
movement.Set (h,0f,v);
movement = movement.normalized * speed * Time.deltaTime;
playerRigidbody.MovePosition (transform.position+movement);
}
void Turning()
{
Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit floorHit;
if(Physics.Raycast(camRay,out floorHit,camRayLength,floorMask))
{
Vector3 playerToMouse = floorHit.point-transform.position ;********
playerToMouse.y = 0f;
Quaternion newRotation = Quaternion.LookRotation (playerToMouse);
playerRigidbody.MoveRotation (newRotation);
}
}
void Animating(float h,float v)
{
bool wakling = h != 0f || v != 0f;
anim.SetBool("IsWalking",wakling);
}
}
Raycasts need a direction, which is usually given as (someVector - someOtherVector). The result from this subtraction is a new vector that takes someVector as the origin point. In your case, the relative vector from the mouse to the player probably never changes, so the subtraction seems not needed. However, it is good practice to use the subtraction of two vectors as direction.
So here's the problem in video form
https://pbs.twimg.com/tweet_video/CPsvjgbWoAACKCp.mp4
When not moving the ship the shield moves around just fine, but when you start moving it can only drag behind you and move a little bit, which is just no good at all. I can't figure out what I've done wrong here!
public class ShieldMovement : MonoBehaviour {
public Transform target; //player shield is attaced to
public float circSpeed = 0.1f; // Speed Shield moves around ship
private Vector3 direction = Vector3.up;
private float distance = 0.8f; // distance from player so it doesn't clip
private float deadzone = 0.15f;
private float separation;
private bool canMove = true;
private Vector3 shipPos;
private Rigidbody2D tRB;
private Rigidbody2D rb;
// Use this for initialization
void Start ()
{
tRB = target.GetComponent<Rigidbody2D>();
rb = GetComponent<Rigidbody2D>();
}
void OnCollisionEnter2D (Collision2D other)
{
canMove = false;
}
void OnCollisionStay2d(Collision2D other)
{
canMove = false;
}
void OnCollisionExit2D (Collision2D other)
{
canMove = true;
}
// Update is called once per frame
void Update () {
float rh = Input.GetAxisRaw("rightH");
float rv = Input.GetAxisRaw("rightV");
shipPos = target.position;
separation = Mathf.Abs((transform.position - shipPos).magnitude);
if(Mathf.Abs(rh) > deadzone || Mathf.Abs(rv) > deadzone)
{
Vector3 targetDir = new Vector3(rh, rv, 0.0f);
direction = Vector3.Slerp(transform.position-shipPos, targetDir, circSpeed);
}
Ray ray = new Ray(shipPos, direction); // cast ray in direction of point on circle shield is to go
if(canMove)
{
transform.position = ray.GetPoint(distance); //move shield to the ray as far as the distance
}
if(separation != distance) //If the shield get torn away from the ship
{
transform.position = ray.GetPoint(distance); //move shield to the ray as far as the distance
}
float angleY = transform.position.y - shipPos.y;
float angleX = -(transform.position.x - shipPos.x);
float angle = Mathf.Atan2 (angleY, angleX) * Mathf.Rad2Deg-90; //Get angle
if(Mathf.Abs(rh) > deadzone || Mathf.Abs(rv) > deadzone)
{
transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1); // keep shield facing outwards in respect to player
}
}
void FixedUpdate ()
{
if(!canMove)
{
tRB.velocity = new Vector2(0.0f, 0.0f);
rb.velocity = new Vector2(0.0f, 0.0f);
}
}
Thanks a million for any help :)
You need to move the shield along with the ship. You can do this by adding the ship velocity to the shield.
Something like:
shipPos = target.position;
transform.position += shipVelocity;
separation = Mathf.Abs((transform.position - shipPos).magnitude);
Or make the shield a child object of the ship.
OK, so all I needed to do was to make the shield a child AND get rid of the conditional statement around the transform.rotation so it wouldn't inherit the parent rotation and ruin the shield. It's the little things!