How can i stop cube from rolling - c#

i got a runner game and cube is my player, the problem is i can't stop cube from rolling. The ground is slippery(friction = 0) but it is still rolling. When i freeze rotation of y axis it seems like lagging so it doesn't work either. Please help me. There is my movement code
I changed values of mass and drag but it didn't help.
public Rigidbody rb;
public float forwardForce = 2000f;
public float sidewaysForce = 500f;
public float acceleration;
public PlayerMovement movement;
void FixedUpdate()
{
rb.AddForce(0, 0, forwardForce * Time.deltaTime);
forwardForce += Time.deltaTime * acceleration;
if (Input.GetKey("d"))
{
rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
if (Input.GetKey("a"))
{
rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
There are no error messages.

you could try and replace Time.deltaTime with Time.fixedDeltaTime since it's in FixedUpdate.

Okay so after trying to help you in the comments I have written a small demo of what you are trying to achieve so you can use it to try and find where you went wrong before and how I would go about doing what you are trying to do.
Cube Controls
using UnityEngine;
public class CubeControl : MonoBehaviour
{
public Rigidbody rb;
public float forwardForce = 2000f;
public float sidewaysForce = 500f;
public float acceleration = 1;
void FixedUpdate()
{
rb.AddForce(0, 0, forwardForce * Time.deltaTime);
forwardForce += Time.deltaTime * acceleration;
//Using the in-built methods uses the keys you were but also the arrow keys
float inputX = Input.GetAxis("Horizontal");
//Check there is input
if (Mathf.Abs(inputX) > float.Epsilon)
{
//set which force direction to use by comparing the inputX value
float force = inputX > 0 ? sidewaysForce : -sidewaysForce;
rb.AddForce(force * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
}
}
There are a couple of changes there but they are commented to explain.
Camera Tracking
using UnityEngine;
public class CameraTracking : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField] private GameObject _cube;
#pragma warning restore 0649
private Vector3 offset;
void Awake()
{
offset = _cube.transform.position + transform.position;
}
void LateUpdate() {
transform.position = _cube.transform.position + offset;
}
}
It uses the initial offset between the cube and Camera that is setup before starting the pressing play.
Tip I recommend not using this but making the camera a child of the cube as this is something that you are calcualting each frame which you don't need too!
Path Generator
using UnityEngine;
using System.Collections;
public class PathGenerator : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField] private GameObject _path1;
[SerializeField] private GameObject _path2;
[SerializeField] private GameObject _cube;
#pragma warning restore 0649
private float _cubeRepositionZDistance;
private float _pathPositionX;
private float _pathPositionY;
//Distance center of path should be behind the cube;
private float _resetDistanceFromCube = 25f;
private void Awake()
{
// You could hard code this but this way you can change the length of each path segment and it will be updated here automatically.
_cubeRepositionZDistance += _path1.transform.localScale.z / 2;
_cubeRepositionZDistance += _path2.transform.localScale.z / 2;
_pathPositionX = _path1.transform.position.x;
_pathPositionY = _path1.transform.position.y;
// Position path2 relative to path1.transform.position
_path2.transform.position = new Vector3(_pathPositionX, _pathPositionY, _path1.transform.position.z + _cubeRepositionZDistance);
StartCoroutine(PathRepositioner());
}
private IEnumerator PathRepositioner()
{
//Can change bool to something like !GameOver
while (true)
{
if (_path1.transform.position.z < _cube.transform.position.z - _resetDistanceFromCube)
{
_path1.transform.position = new Vector3(_pathPositionX, _pathPositionY, _path2.transform.position.z + _cubeRepositionZDistance);
}
if (_path2.transform.position.z < _cube.transform.position.z - _resetDistanceFromCube)
{
_path2.transform.position = new Vector3(_pathPositionX, _pathPositionY, _path1.transform.position.z + _cubeRepositionZDistance);
}
yield return null;
}
}
}
Doing it this way you are reusing the same 2 path segements and not creating clones all the time, you can change it to use 3 or more if needed.
Scene Setup
Position the cube and then position the path1 segement under the Cube.
Assign all required GameObjects to the scripts in the inspector.
Press Play!
Sidenote: It is recommended to move the path segements not the Cube(Player) when doing an endless runner like this but as you are new to this I suggest reading up on that when you get a chance.

Related

How to make a rigidbody moving at a constant speed using the velocity function go up and down slopes?

In my game, I have a vehicle using a rigidbody that moves forward (relative to the front of the vehicle) at a constant rate using the rigidbody velocity function. The vehicle also may turn 90 degrees to the right and back, of course causing the direction it is moving to rotate. The vehicle drives on a floating platform, and if driven off, the velocity function is stopped so that the car may properly fall off using rigidbody physics.
I want to have slopes at various points in the game, and since the vehicle moves at a constant speed, the vehicle should be able to drive up and down a slope automatically. The issue is that I have to directly control the rigidbody's velocity to make it drive at a constant speed, so when the vehicle drives into a slope, the velocity function keeps pushing it forward without properly rotating, not letting it properly drive up the slope. How should I go about fixing this? Should I be using the rigidbody velocity function at all in this case?
For reference, here is the script I am using for vehicle movement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
[SerializeField] private GameObject followCamera;
[SerializeField] private AnimationCurve lerpCurve;
[SerializeField] private float turnSpeed;
[SerializeField] private float speed;
private static float turnTimer = 2f;
private float turnTimeElapsed;
private float clampedTimeElapsed;
private float lerpTimer;
Rigidbody ridgy;
LayerMask groundLayer;
private void Start()
{
groundLayer = LayerMask.GetMask("Ground");
ridgy = this.GetComponent<Rigidbody>();
turnTimeElapsed = 0f;
Quaternion endRot = Quaternion.Euler(0f, 90f, 0f);
}
private void Update()
{
if (Input.GetKey(KeyCode.Space) && turnTimeElapsed < turnTimer)
{
turnTimeElapsed += turnSpeed * Time.deltaTime;
}
else if (!Input.GetKey(KeyCode.Space) && turnTimeElapsed > 0)
{
turnTimeElapsed -= turnSpeed * Time.deltaTime;
}
clampedTimeElapsed = Mathf.Clamp(turnTimeElapsed, 0f, turnTimer);
lerpTimer = clampedTimeElapsed / turnTimer;
lerpTimer = lerpCurve.Evaluate(lerpTimer);
}
private void FixedUpdate()
{
if (Physics.CheckBox(transform.position, new Vector3(.5f, .5f, .5f), Quaternion.identity, groundLayer))
{
if (lerpTimer > 0f && lerpTimer < .75f)
{
speed = 45;
}
else
{
speed = 15;
}
ridgy.rotation = new Quaternion
(
0,
Mathf.Sin(lerpTimer * Mathf.PI / 4f),
0,
Mathf.Cos(lerpTimer * Mathf.PI / 4f)
);
ridgy.velocity = transform.forward * speed;
}
else
{
followCamera.GetComponent<CameraFollow>().enabled = false;
return;
}
}
}

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.

Diagonal movements are faster than normal movements

FIRST : SORRY FOR MY ENGLISH !!!
Hello everyone, i'm very new into Unity (5 days).
Today i've make a script for the basics movements with a rigid-bodie, BUT the diagonal movements are faster than the normal movements.. I search on Internet but I don't find a post that i can understand.
So here my script.
Also if you know how to not move when we jump, or when we jump into a direction, it follow this direction, tell me. (I know my english is terrible.) Also, i'm new into this website.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovements : MonoBehaviour
{
[SerializeField] private float walkingSpeed;
[SerializeField] private float runningSpeed;
[SerializeField] private float jumpForce;
[SerializeField] private float jumpRaycastDistance;
private Rigidbody rb;
float speed;
Vector3 movement;
/////////////////////////////////////////////////////
void Start()
{
rb = GetComponent<Rigidbody>();
}
/////////////////////////////////////////////////////
void Update()
{
Jumping();
}
/////////////////////////////////////////////////////
private void FixedUpdate()
{
Movements();
}
/////////////////////////////////////////////////////
private void Movements()
{
float hAxis = Input.GetAxisRaw("Horizontal");
float vAxis = Input.GetAxisRaw("Vertical");
if(Input.GetButton("Run"))
{
Vector3 movement = new Vector3(hAxis, 0, vAxis) * runningSpeed * Time.deltaTime;
Vector3 newPosition = rb.position + rb.transform.TransformDirection(movement);
rb.MovePosition(newPosition);
}
else
{
Vector3 movement = new Vector3(hAxis, 0, vAxis) * walkingSpeed * Time.deltaTime;
Vector3 newPosition = rb.position + rb.transform.TransformDirection(movement);
rb.MovePosition(newPosition);
}
}
/////////////////////////////////////////////////////
private void Jumping()
{
if(Input.GetButtonDown("Jump"))
{
if (isGrounded())
{
rb.AddForce(0, jumpForce, 0, ForceMode.Impulse);
}
}
}
/////////////////////////////////////////////////////
private bool isGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, jumpRaycastDistance);
}
}
You need to clamp your velocity in order to keep it same. Look into Vector3.ClampMagnitude()
velocity = Vector3.ClampMagnitude(velocity, _movementSpeed);
velocity.y = playerVelocity.Y; // keeping your Y velocity same since you have jumping.
playerVelocity = velocity;
EDIT: in your case it should be something like this.
_maxSpeed is the speed limit.
private void FixedUpdate()
{
Movements();
var clampedVelocity = Vector3.ClampMagnitude(rb.velocity, _maxSpeed);
clampedVelocity.y = rb.velocity.y;
rb.velocity = clampedVelocity;
}
Try normalizing the vector. (more info is on unity docs, but normalize() will make sure that the sum of all the vector's values isnt above 1.

How can I repeat this boost (push)?

I dont understand how I can make this shotgun jumps in my version of Unity: https://www.youtube.com/watch?v=FUkdz8jYt3w
How does this work?
Im using "First Person Controller" that looks like capsule
There are images: https://imgur.com/a/uvfAePX
This is for old version of Unity 4.5.5. I've tried RigidBody, but nothing happened. I've tried Transform, but again, no result.
First Person Controller:
using UnityEngine;
using System.Collections;
public class run : MonoBehaviour
{
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
public Transform character;
public int CharacterForce = 5000;
public int time = 1;
void Update()
{
CharacterController controller =
GetComponent<CharacterController>();
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);
if (Input.GetMouseButtonDown(0))
{
Transform BulletInstance = (Transform)Instantiate(character, GameObject.Find("CameraRSP").transform.position, Quaternion.identity);
BulletInstance.GetComponent<Rigidbody>().AddForce(transform.forward * CharacterForce);
}
}
}
"Grenade" code:
using UnityEngine;
using System.Collections;
public class grenade : MonoBehaviour
{
public Transform GrenadeF;
public int force = 500;
public float radius;
void Start()
{
Collider[] col = Physics.OverlapSphere(transform.position, radius);
foreach (Collider c in col)
{
c.GetComponent<Rigidbody>().AddExplosionForce(force, transform.position, radius);
}
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(transform.position, radius);
}
}
When I used Transform I expected that this would work in ANY direction, but it worked in only one.
When I used RigidBody I expected that this would WORK, but my capsule didnt even moved.
Checkout the optional upwardsModifier parameter of
AddExplosionForce(float explosionForce, Vector3 explosionPosition, float explosionRadius, float upwardsModifier = 0.0f, ForceMode mode = ForceMode.Force));
(The API for Unity 4 is no longer available but I guess it should have been the same there)
Adjustment to the apparent position of the explosion to make it seem to lift objects.
and
Using this parameter, you can make the explosion appear to throw objects up into the air, which can give a more dramatic effect rather than a simple outward force. Force can be applied only to an active rigidbody.
By default it is 0 so if you don't pass it there won't be any upwards force.
As you can see in the example from the API
Vector3 explosionPos = transform.position;
Collider[] colliders = Physics.OverlapSphere(explosionPos, radius);
foreach (Collider hit in colliders)
{
Rigidbody rb = hit.GetComponent<Rigidbody>();
// |
// v
if (rb) rb.AddExplosionForce(power, explosionPos, radius, 3.0f);
}
they passed e.g. 3.0f as upwardsModifier. This makes the explosion
appear to be centred 3.0 units below its actual position for purposes of calculating the force direction (ie, the centre and the radius of effect are not modified).
Note: Typed on smartphone so no warrenty but I hope the idea gets clear

transform.Translate isn't cutting it and rigidbody.AddRelativeForce doesn't move my character (Unity and c#)

I'm making a game in Unity 5 (3D) and am using c# for scripting. So I basically have a third person dude running around with 8 direction controls (WASD) and the way I have set it up now is like this (ignore all the public variables for testing):
public class Player8D : MonoBehaviour
{
public float moveSpeed;
public float moveSpeedMax = 13.5F;
public float turnSpeed = 4F;
public float transitionSpeed = 10F;
private float moveSmooth = 0.0F;
public float moveSmoothTime = 10F;
private Animator anim;
private Rigidbody rb;
private CharacterController cc;
void Start()
{
anim = gameObject.GetComponentInChildren<Animator>();
rb = gameObject.GetComponentInChildren<Rigidbody>();
cc = gameObject.GetComponentInChildren<CharacterController>();
}
void Update()
{
Vector3 NextDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
if (NextDir != Vector3.zero) //When movement input is happening
{
anim.SetInteger("Run", 1); //Animation stuff
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(NextDir), Time.deltaTime * turnSpeed);
moveSpeed = Mathf.SmoothDamp(moveSpeed, moveSpeedMax, ref moveSmooth, moveSmoothTime / 100);
} else
{
moveSpeed = Mathf.SmoothDamp(moveSpeed, 0.00F, ref moveSmooth, transitionSpeed / 100);
anim.SetInteger("Run", 0); //Animation stuff
anim.CrossFade("Idle", transitionSpeed / 100);
}
transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed); //Movement code
}
}
This gave me the best feeling due to how it moves in the direction it's facing, rather than in 8 distinct world directions like with cc.Move. That being said it has the caveat of not being in physics, which I kinda need for OnTriggerEnter and falling realistically and it makes going uphill strange. I have no idea how to manage the rb.AddForce or AddRelativeForce functions, as they don't move my character when I replace transform.Translate with them, no matter how great the force is.
How do I change the code and components to get my character moving through physics?
Here is a screenshot of my scene hierarchy:

Categories