wrote a script to move the player by dragging it, so at first, I moved the player with transform.position and it worked perfectly so I said its time to move it with rigidbody to make it collides with objects,
so I tried rigidbody.velocity but it not moving smoothly. so how to make this works like transform.position?
this is the script:
void Update()
{
if(Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved)
{
transform.position = new Vector3(
transform.position.x + touch.deltaPosition.x * speedmodifier,
transform.position.y,
transform.position.z + touch.deltaPosition.y * speedmodifier);
}
}
}
When using Rigidbody you want to do all physics related stuff in FixedUpdate. then you probably would not use velocity but set fix positions using Rigidbody.MovePosition
You should still get the User input via Update though.
I would separate the logic. Something like maybe
[SerializeField] private Rigidbody _rigidbody;
private Vector3 targetPosition;
private void Start()
{
targetPosition = transform.position;
if(!_rigidbody) _rigidbody = GetComponent<Rigidbody>();
// since this rigibody is going to be moved via code not Physics it should be kinemtic
_rigibody.isKinematic = true;
// in order to smooth the movement
_rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
}
void Update()
{
if(Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved)
{
targetPosition += Vector3.right * touch.deltaPosition.x * speedmodifier;
targetPosition += Vector3.forward * touch.deltaPosition.y * speedmodifier;
}
}
}
private void FixedUpdate()
{
_rigidbody.MovePosition(targetPosition);
}
Related
I am new to game development and trying to build an endless runner game just for my hands-on on Unity3D game development, it was running smoothly before applying jump functionality to the player, here are my code for player movement.
public class RockeyMovement : MonoBehaviour
{
public float rockyMoveForwardSpeed = 5f;
public float rockyMoveLeftRightSpeed = 4f;
public Vector3 jump;
public float jumpForce = 2.0f;
public bool isGrounded;
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
jump = new Vector3(0.0f, 2.0f, 0.0f);
}
void OnCollisionStay()
{
isGrounded = true;
}
void Update()
{
transform.Translate(Vector3.forward * Time.deltaTime * rockyMoveForwardSpeed, Space.World);
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
if (this.gameObject.transform.position.x > LevelControl.leftSide)
{
transform.Translate(Vector3.left * Time.deltaTime * rockyMoveLeftRightSpeed);
}
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
if (this.gameObject.transform.position.x < LevelControl.rightSide)
{
transform.Translate(Vector3.left * Time.deltaTime * rockyMoveLeftRightSpeed * -1);
}
}
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(jump * jumpForce, ForceMode.Impulse);
isGrounded = false;
}
}
}
Player Inspector
Errors
Hierarchy
As you can see I just drop Main Camera on to player so that camera follow player,
That is how my game is behaving
My game was working fine before implementing that jump functionality to the player. as i am new please tell me how to solve that issue which i am facing.
Instead of attaching your camera as a child of a player you could use PositionConstraint just align your camera relative to the player with offsets then just attach the PositionConstraint component on your camera with following settings
By doing this your camera will only follow your player's position.
I am trying to move my Player by touch and make it collides so I wrote this script but the problem is that my player is not colliding with the other objects so how to make it collide so how to fix this?
[SerializeField] private Rigidbody rb;
private Vector3 targetPosition;
private void Start()
{
targetPosition = transform.position;
if (!rb)rb = GetComponent<Rigidbody>();
// since this rigibody is going to be moved via code not Physics it should be kinemtic
rb.isKinematic = true;
// in order to smooth the movement
rb.interpolation = RigidbodyInterpolation.Interpolate;
}
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved)
{
targetPosition += Vector3.right * touch.deltaPosition.x * speedmodifier;
targetPosition += Vector3.forward * touch.deltaPosition.y * speedmodifier;
}
}
}
private void FixedUpdate()
{
rb.MovePosition(targetPosition);
}
You can use MovePosition() with non kinematic rigidbodys, but it will then work like transform.position=newPosition and teleports the object to the new position (rather than performing a smooth transition). Furthermore you can move a kinematic rigidbody object from a script by modifying its Transform Component but it will not respond to collisions and forces like a non-kinematic rigidbody.
So if you want your rigidbody to be correctly affected by Physics you need to use the AddForce() Method and set your rigidBody to Dynamic.
Example:
player.AddForce(new Vector2(speed, 0), ForceMode2D.Impulse);
After my player object touches the wall it sometimes starts to move and rotate on it's own. I tried to increase player object weight and it helps, but i don't think it's a good approach as tiny movement never dissapears.
Player is rigidbody with box collider attached.
isKinematic - false;
useGravity - true;
XYZ rotation is fixed and Y coordinate position is fixed.
Walls have box collider but have no rigidbody.
Ground has no collider as Y position is fixed and player object doesn't touch the ground.
Game is network based so i have photon rigidbody view component attached to player as well.
Code (C#) which moves player:
public void Update()
{
if (!photonView.IsMine || !controllable)
{
return;
}
if (shootingTimer > 0.0)
{
shootingTimer -= Time.deltaTime;
}
m_MovementInputValue = Input.GetAxis(m_MovementAxisName);
if (m_MovementInputValue == 0.0f)
{
m_MovementInputValue = joystick.Vertical;
}
m_TurnInputValue = Input.GetAxis(m_TurnAxisName);
if (m_TurnInputValue == 0.0f)
{
m_TurnInputValue = joystick.Horizontal;
}
Vector3 vector = new Vector3(
m_TurnInputValue,
rigidbody.velocity.y,
m_MovementInputValue
);
MovementVector = Quaternion.AngleAxis(60, Vector3.up) * vector;
EngineAudio();
}
public void FixedUpdate()
{
if (!photonView.IsMine || !controllable)
{
return;
}
Move();
Turn();
}
private void Move()
{
// Adjust the position of the tank based on the player's input.
// Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;
// rigidbody.MovePosition(rigidbody.position + movement);
Vector3 movement = MovementVector * m_Speed * Time.deltaTime;
rigidbody.MovePosition(rigidbody.position + movement);
}
private void Turn()
{
// Adjust the rotation of the tank based on the player's input.
// float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;
// Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);
// rigidbody.MoveRotation(rigidbody.rotation * turnRotation);
if (m_TurnInputValue != 0.0f || m_MovementInputValue != 0.0f)
{
rigidbody.rotation = Quaternion.LookRotation(MovementVector);
}
}
Check to make sure the component (such as a rigidbody) is attached to the right object (gameobject - parent vs. child objects). Also, the fact that it is constantly rotating is curious... it makes me think it has something to do with the Time.DeltaTime, but I see that's only being applied to your Vector3 movement, and not in your rotation function... Just curious, what happens when you remove the Time.DeltaTime part from your movement Vector3?
How can I add a force to a rigidbody2D game object and keep it moving at a fixed velocity? The game object also has a bounce material attached.
private Rigidbody2D rb2D;
private float thrust = 10.0f;
void Start() {
}
void FixedUpdate() {
rb2D.AddForce(new Vector2(0, 1) * thrust);
}
This is what i got off of the Unity documentations website but this doesn't seem to do anything.
Here is the code I ended up going with and it appears to be functioning properly. The Vector2 direction and speeds can be adjusted depending on mass/ gravity.
float topSpeed = 15;
private Rigidbody2D rb2D;
private float thrust = 0.1f;
void Start()
{
rb2D = gameObject.GetComponent<Rigidbody2D>();
rb2D.AddForce(new Vector2(0, 1) * thrust);
}
void Update()
{
if (rb2D.velocity.magnitude > topSpeed || rb2D.velocity.magnitude < topSpeed)
rb2D.velocity = rb2D.velocity.normalized * topSpeed;
}
Your code as written, once it works will accelerate the rigidbody infinitely. You'll want to cap the velocity at its maximum speed: http://answers.unity.com/answers/330805/view.html
rigidbody.AddForce(new Vector2(0, 1) * thrust * Time.deltaTime);
if (rigidbody.velocity.magnitude > topSpeed)
rigidbody.velocity = rigidbody.velocity.normalized * topSpeed;
If you want it to immediately set the velocity to the fixed value, then you can just set the velocity on every frame:
https://docs.unity3d.com/ScriptReference/Rigidbody-velocity.html
void FixedUpdate()
{
if (Input.GetButtonDown("Jump"))
{
// the cube is going to move upwards in 10 units per second
rb2D.velocity = new Vector3(0, 10, 0);
moving = true;
Debug.Log("jump");
}
if (moving)
{
// when the cube has moved over 1 second report it's position
t = t + Time.deltaTime;
if (t > 1.0f)
{
Debug.Log(gameObject.transform.position.y + " : " + t);
t = 0.0f;
}
}
}
Your code doesn't show it so in case you aren't doing it yet, you'll want to make sure that rb2D is actually set to the Rigidbody2d on the object you want to manipulate. E.g. by doing in the start method:
void Start()
{
rb2D = gameObject.GetComponent<Rigidbody2D>();
}
I'm using the Charactercontroller component for the movement of my character.
The thing I'm trying to achieve is for the character to go when I'm clicking with the mouse. For that, I'm rotating where I click and then going forward to the point where the ray collider with my terrain.
The character does move and goes to the point I want.
The problem is when walking into a ramp, for example, the character keeps walking in the air and does not go down (gravity problem as far as I can understand although when I test putting the character in the air when the editor it does go down) it stops above when it supposed to go and starts spinning really fast.
Here's my movement script
private float gravity = 1f;
Animator anim;
CharacterController charController;
private float mvtSpeed = 3f;
private float distanceToPoint;
Vector3 playerMvt;
bool canMove = false;
CollisionFlags collisionFlags;
Ray ray;
RaycastHit hit;
Vector3 PlayerTarget;
float height;
private void Awake()
{
anim = GetComponent<Animator>();
charController = GetComponent<CharacterController>();
}
void MoveThePlayer()
{
if (Input.GetMouseButton(0))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit)) {
if (hit.collider is TerrainCollider)
{
if (Vector3.Distance(transform.position, hit.point) >= 0.5f)
{
canMove = true;
anim.SetFloat("Walk", 1.0f);
PlayerTarget = hit.point;
}
}//terrain collider
}//raycast
}//mouse Down
if (canMove)
{
Vector3 targetTemp = new Vector3(PlayerTarget.x, transform.position.y, PlayerTarget.z);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetTemp - transform.position), 15.0f * Time.deltaTime);
playerMvt = transform.forward * mvtSpeed * Time.deltaTime;
if (Vector3.Distance(transform.position, PlayerTarget) <= 0.1f)
{
anim.SetFloat("Walk", 0f);
playerMvt.Set(0f, 0f, 0f);
}
}//canMove
}
private void Update()
{
MoveThePlayer();
charController.Move(playerMvt);
if (!charController.isGrounded)
{
playerMvt.y -= gravity * Time.deltaTime;
}
}
A few things.
canMove is never reset to false, it should probably reset in here
if (Vector3.Distance(transform.position, PlayerTarget) <= 0.1f)
{
anim.SetFloat("Walk", 0f);
playerMvt.Set(0f, 0f, 0f);
}
This code has no impact where its located right now:
if (!charController.isGrounded)
{
playerMvt.y -= gravity * Time.deltaTime;
}
You apply gravity to playerMvt.y after you have already moved the player, and the next frame you will re-assign playerMvt here:
playerMvt = transform.forward * mvtSpeed * Time.deltaTime;
So change it up to this
private void Update()
{
MoveThePlayer();
if (!charController.isGrounded)
{
playerMvt.y -= gravity * Time.deltaTime;
}
charController.Move(playerMvt);
}