Unity Animator component unnecessarily overriding scripted position of Game Objects - c#

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.

Related

The CineMachine Camera ruin the 2d parallax Effect because its shaking

I am working in a 2d platform game I applied cinemachine camera and parallax script to give a good effect ,but the parallax is shaking and vibrating hard , I found out that the cinamchine was the reason because the camera it shaking, when I disabled the cinemachine it work smoothly
here is the parallax code
private float startpos;
private GameObject cam;
[SerializeField] private float parallax;
[SerializeField] private float speed = 0.1f;
// Start is called before the first frame update
void Start()
{
cam = GameObject.Find("Main Camera");
startpos = transform.position.x;
}
// Update is called once per frame
void Update()
{
float distance = (cam.transform.position.x * parallax);
transform.position = new Vector3(startpos + distance, transform.position.y, transform.position.z);
}
and the settings of the MC vcam1
enter image description here
please any help I dont find any on with that problem
You could try setting the CinemachineBrain update method to Manual Update and then just calling ManualUpdate() in another script.
using UnityEngine;
using Cinemachine;
public class ManualBrainUpdate : MonoBehaviour
{
public CinemachineBrain cineBrain;
public float smoothTime;
private void Start()
{
cineBrain = GetComponent<CinemachineBrain>();
}
void Update()
{
cineBrain.ManualUpdate();
}
}
To avoid any kind of jitter in Unity (like what the camera is adding to distance when it shakes) use the various SmoothDamp functions e.g. https://docs.unity3d.com/ScriptReference/Vector3.SmoothDamp.html:
public float smoothTime = 0.3f; // adjust this to taste
private float distance;
private Vector3 velocity = Vector3.zero;
private Vector3 targetPos
void Update()
{
distance = cam.transform.position.x * parallax;
targetPos = new Vector3(startpos + distance, transform.position.y, transform.position.z)
transform.position = Vector3.SmoothDamp(transform.position, targetPos, ref velocity, smoothTime);
}

Rotate enemy character to see player character

I am making the enemy character to follow the player character.
In the FixedUpdate method the enemy character move toward the player character,
then in the Update method character rotates to the player character.
However, with this script, somehow enemy character is just nudging and gets stuck.
Where is the mistake, what's wrong???
public class enemy : MonoBehaviour
{
GameObject tObj;
private Vector3 latestPos;
public string targetObjectName;
public float speed = (float)1.0;
void Start()
{
tObj = GameObject.Find("player");
latestPos = transform.position;
}
void Update()
{
Vector3 diff = transform.position - latestPos;
latestPos = transform.position;
if (diff.magnitude > 0.01f)
{
transform.rotation = Quaternion.LookRotation(diff);
}
}
void FixedUpdate(){
Vector3 dir = (tObj.transform.position - this.transform.position).normalized;
float vx = dir.x * speed;
float vz = dir.z * speed;
this.transform.Translate((float)(vx / 50.0),0,(float)(vz / 50.0));
}
}
Use Package Manager "Standard Assets", Inside Unity put two FPSController one should be Player and the second can be Enemy.
I know this does not answers your question but its a faster way to ad Enemy.
AI Settings
Just remove the camera, Audio Source and First Person Controller Script as in image.
The Code for AI:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowAI : MonoBehaviour
{
public CharacterController _controller;
public Transform target;
public GameObject Player;
[SerializeField]
float _moveSpeed = 2.0f;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update() {
Vector3 direction = target.position - transform.position;
direction = direction.normalized;
Vector3 velocity = direction * _moveSpeed;
_controller.Move(velocity * Time.deltaTime);
Vector3 lookVector = Player.transform.position - transform.position;
lookVector.y = transform.position.y;
Quaternion rot = Quaternion.LookRotation(lookVector);
transform.rotation = Quaternion.Slerp(transform.rotation, rot, 1);
}
}

Can't rotate and move at the same time

I'm currently developing an FPS shooter in Unity 3D. I'm fairly new to Unity and I've been having a bit of trouble with my player movement script. Individually everything seems to work, I can rotate and move the player freely, however when I try doing the two simultaneously my player seems to lock and won't rotate.
Sometimes jumping or moving to higher ground on the terrain seems to fix the issue, however I ran a few checks with gravity disabled, no colliders, and with the player well above ground, so the problem seems to be with the script. I've also done a bit of debugging and the Rotate() code does run, just the rotation amount doesn't seem to change.
Here is the player movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerMov : MonoBehaviour
{
[SerializeField]
private Camera cam;
[SerializeField]
private float speed = 5f;
[SerializeField]
private float looksensitivity = 4f;
[Header("Camera View Lock:")]
[SerializeField] //min and max amount for looking up and down (degrees)
private float lowlock = 70f;
[SerializeField]
private float highlock = 85f;
private Rigidbody rb;
private float currentrotx; //used later for calculating relative rotation
public Vector3 velocity;
public Vector3 rotation; // rotates the player from side to side
public float camrotation; // rotates the camera up and down
public float jmpspe = 2000f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
CalcMovement();
CalcRotation();
Rotate();
}
void FixedUpdate()
{
Move();
}
private void CalcRotation()
{
float yrot = Input.GetAxisRaw("Mouse X"); //around x axis
rotation = new Vector3(0f, yrot, 0f) * looksensitivity;
float xrot = Input.GetAxisRaw("Mouse Y"); //around y axis
camrotation = xrot * looksensitivity;
}
private void CalcMovement()
{
float xmov = Input.GetAxisRaw("Horizontal");
float zmov = Input.GetAxisRaw("Vertical");
Vector3 movhor = transform.right * xmov;
Vector3 movver = transform.forward * zmov;
velocity = (movhor + movver).normalized * speed;
}
void Move()
{
//move
if (velocity != Vector3.zero)
{
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);
}
//jump
if (Input.GetKeyDown(KeyCode.Space))
{
//add double jump limit later!
rb.AddForce(0, jmpspe * Time.deltaTime, 0, ForceMode.Impulse);
}
}
void Rotate()
{
//looking side to side
rb.MoveRotation(rb.rotation * Quaternion.Euler(rotation));
// camera looking up and down
currentrotx -= camrotation;
currentrotx = Mathf.Clamp(currentrotx, -lowlock, highlock);
cam.transform.localEulerAngles = new Vector3(currentrotx, 0, 0);
}
}
Here are the relevant components attached to my player:
(The player has a couple more components attached but I ran tests without them and the problem still occurs)
Like I said I'm a bit of a unity novice, so i'm sure I missed something small but I just can't seem to place my finger on it, I've been stuck on this for a while so any help is much appreciated.
SOLVED:
It seems the problem I had was because I was running the scene from my laptop and not a desktop which I assume is what the Unity input was built for.

How can i stop cube from rolling

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.

Trying to create a 3rd person controller in Unity but the player is not moving

This is what I have so far.
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
CharacterController control;
[SerializeField]
float moveSpeed = 5.0f;
[SerializeField]
float jumpSpeed = 20.0f;
[SerializeField]
float gravity = 1.0f;
float yVelocity = 0.0f;
// Use this for initialization
void Start () {
control = GetComponent<CharacterController> ();
}
// Update is called once per frame
void Update ()
{
Vector3 direction = new Vector3 (Input.GetAxis ("Horizontal"), 0, Input.GetAxis ("Vertical"));
Vector3 velocity = direction * moveSpeed;
if (control.isGrounded) {
if (Input.GetButtonDown ("Jump")) {
yVelocity += jumpSpeed;
}
} else {
yVelocity -= gravity;
}
velocity.y = yVelocity;
control.Move (velocity*Time.deltaTime);
}
}
I'm following a tutorial, and it looks like everything is the same, but the player is not moving.
If it is all same with tutorial, your problem must be about your input settings. Check your "Horizontal", "Vertical", "Jump" from Edit -> Project Settings -> Input
Then on inspector look at variables under Axis list to check them if they assigned true, maybe there is no Horizontal or Vertical variable.

Categories