Float is going up slower after export - c#

i want to multiply a float. in the unity editor everything is ok too, in the build it is going up slower all of a sudden.
i tried reimporting all assets and restart my pc but that does not help either.
I tried to build it again but that did not help.
I do not know what to do now, does anyone know how to fix this problem?
here is my build output: https://i.stack.imgur.com/ry5PI.png
code:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class PlayerController : MonoBehaviour
{
[Header("")]
[Header("Move Settings")]
[Header("")]
public float MovementSpeed = 5f;
public float SprintSpeed = 7f;
public float JumpForce = 5f;
public float minJumpForce = 3f;
[Header("")]
[Header("Stamina Settings")]
[Header("")]
public float fillStamina = 1f;
public float MaxStamina = 10000f;
public float Stamina = 10000f;
public Slider staminaBar;
public GameObject SliderFill;
public GameObject SliderB;
[Header("")]
[Header("Health Settings")]
[Header("")]
public float fillHealth = 1f;
public float MaxHealth = 100f;
public float Health = 100f;
public Slider HealthBar;
[Header("")]
[Header("Player Settings")]
[Header("")]
Rigidbody2D body;
public static PlayerController instance;
public GameObject DeathObj;
float horizontal;
float vertical;
private Rigidbody2D _rigidbody;
private bool Sprint = false;
//private bool ActivateLowStamina = false;
//private bool LowStamina = false;
private float move;
private void Awake()
{
instance = this;
}
void Start()
{
_rigidbody = GetComponent<Rigidbody2D>();
//body = GetComponent<Rigidbody2D>();
Stamina = MaxStamina;
staminaBar.maxValue = MaxStamina;
staminaBar.value = MaxStamina;
HealthBar.maxValue = MaxHealth;
HealthBar.value = MaxHealth;
//ActivateLowStamina = false;
//lowTxt.gameObject.SetActive(false);
}
void Update()
{
horizontal = Input.GetAxisRaw("Horizontal");
vertical = Input.GetAxisRaw("Vertical");
//transform.rotation = Quaternion.identity;
staminaBar.value = Stamina;
HealthBar.value = Health;
//var movement = Input.GetAxis("Horizontal");
if (Health < 1)
{
Die();
}
if (Stamina <= 0)
{
Stamina = 0;
}
if(Health <= 0)
{
Health = 0;
}
if (Stamina < 3000)
{
SliderFill.GetComponent<Image>().color = new Color32(213, 217, 0, 255);
SliderB.GetComponent<Image>().color = new Color32(11, 217, 0, 47);
}
else
{
SliderFill.GetComponent<Image>().color = new Color32(11, 217, 0, 255);
SliderB.GetComponent<Image>().color = new Color32(0, 255, 12, 47);
}
if (Input.GetKey("left shift"))
{
Sprint = true;
}
//if(Stamina < 100)
//{
// ActivateLowStamina = false;
//}
//else
//{
// ActivateLowStamina = true;
//}
//if(ActivateLowStamina == true)
// {
// lowTxt.gameObject.SetActive(true);
// }
if (Mathf.Abs(_rigidbody.velocity.x) == 0f && Stamina < MaxStamina && Mathf.Abs(_rigidbody.velocity.y) == 0f)
{
Stamina += fillStamina;
}
Health += fillHealth;
if (Input.GetButtonDown("Jump") && Mathf.Abs(_rigidbody.velocity.y) < 0.001f) {
if(Stamina > 10)
{
_rigidbody.AddForce(new Vector2(0, JumpForce), ForceMode2D.Impulse);
//_rigidbody.AddForce(Vector2.up * JumpForce);
UseStamina(700);
}
else
{
_rigidbody.AddForce(new Vector2(0, minJumpForce), ForceMode2D.Impulse);
//_rigidbody.AddForce(Vector2.up * JumpForce);
UseStamina(300);
}
}
}
public void UseStamina(float amount)
{
if (Stamina - amount >= 0)
{
Stamina -= amount;
}
}
private void FixedUpdate()
{
move = Input.GetAxis("Horizontal");
if (Sprint == true && Stamina > 10)
{
_rigidbody.velocity = new Vector2(move * SprintSpeed, _rigidbody.velocity.y);
if (Mathf.Abs(_rigidbody.velocity.x) != 0f)
{
UseStamina(10);
}
Sprint = false;
}
else
{
if (Stamina > 10)
{
_rigidbody.velocity = new Vector2(move * MovementSpeed, _rigidbody.velocity.y);
if(Mathf.Abs(_rigidbody.velocity.x) != 0f)
{
UseStamina(2f);
}
}
else
{
_rigidbody.velocity = new Vector2(move * 1f, _rigidbody.velocity.y);
}
}
//if(Mathf.Abs(_rigidbody.velocity.x) != 0f)
//{
//Stamina -= 1;
//}
}
public void Die()
{
if(Health < 1)
{
Time.timeScale = 0;
DeathObj.SetActive(true);
//SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
}
//_rigidbody.velocity = new Vector2(horizontal * MovementSpeed, vertical * SprintSpeed);
//transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * SprintSpeed;
//transform.Translate(new Vector3(-3f, 0, 0) * Time.deltaTime);
//_rigidbody.velocity = new Vector2(MovementSpeed, 0);
//_rigidbody.AddForce(new Vector2(MovementSpeed, MovementSpeed));
//transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * MovementSpeed;
//_rigidbody.velocity = new Vector2(horizontal * MovementSpeed, vertical * MovementSpeed);
//transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * 3f;
//body.velocity = new Vector2(horizontal * MovementSpeed, vertical * MovementSpeed);
//var movement = Input.GetAxis("Horizontal"); ```

What you experience is the typical frame-rate dependent code.
Every frame you do
Stamina += fillStamina;
and
Health += fillHealth;
However, what if on one device you have 60 frames per second, on another weaker device only 30?
On the weaker device it will take twice as long to raise the value.
Therefore you should use Time.deltaTime which is the time passed since the last frame was rendered.
By multiplying
X * Time.deltaTime
you convert a value X from value per frame into a value per second which is now independent of the capacity of the device and the frame-rate. Across all devices it will now always take the same effective time in seconds.
You will of course have to tweak your values but in general you would do e.g.
Stamina += fillStaminaPerSecond * Time.deltaTime;
and accordingly
Health += fillHealthPerSecond * Time.deltaTime;
And accordingly also for the continous usages
UseStamina(10 * Time.deltaTime);
and
UseStamina(2f * Time.deltaTime);
as said you might have to adjust the values since now they are more or less decided by 60 (whatever the frame-rate is).
However, for the single event calls for the jump you do not want/need the Time.deltaTime since these are no continous calls.
Btw instead of using GetComponent over and over again rather do it once in Awake or Start and store the reference in a field and later reuse it!
And instead of
[Header("")]
you should probably rather use
[Space]
;)

Related

Unexpected Cube movement when rotating camera

I am currently making an FPS game and I have some problems with camera movement. When I add a child object to the camera, and when I rotate the camera, the child object deforms.
I followed this tutorial to get my FPS movement. https://www.youtube.com/watch?v=XAC8U9-dTZU/
Here is my camera movement script and my player movement one:
using UnityEngine;
public class MoveCamera : MonoBehaviour {
public Transform player;
void Update() {
transform.position = player.transform.position;
}
}
// Some stupid rigidbody based movement by Dani
using System;
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
//Assingables
public Transform playerCam;
public Transform orientation;
//Other
private Rigidbody rb;
//Rotation and look
private float xRotation;
private float sensitivity = 150f;
private float sensMultiplier = 1f;
//Movement
public float moveSpeed = 4500;
public float maxSpeed = 20;
public bool grounded;
public LayerMask whatIsGround;
public float counterMovement = 0.175f;
private float threshold = 0.01f;
public float maxSlopeAngle = 35f;
//Crouch & Slide
private Vector3 crouchScale = new Vector3(1, 0.5f, 1);
private Vector3 playerScale;
public float slideForce = 400;
public float slideCounterMovement = 0.2f;
//Jumping
private bool readyToJump = true;
private float jumpCooldown = 0.25f;
public float jumpForce = 550f;
//Input
float x, y;
bool jumping, sprinting, crouching;
//Sliding
private Vector3 normalVector = Vector3.up;
private Vector3 wallNormalVector;
void Awake() {
rb = GetComponent<Rigidbody>();
}
void Start() {
playerScale = transform.localScale;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
private void FixedUpdate() {
Movement();
}
private void Update() {
MyInput();
Look();
}
/// <summary>
/// Find user input. Should put this in its own class but im lazy
/// </summary>
private void MyInput() {
x = Input.GetAxisRaw("Horizontal");
y = Input.GetAxisRaw("Vertical");
jumping = Input.GetButton("Jump");
crouching = Input.GetKey(KeyCode.LeftControl);
//Crouching
if (Input.GetKeyDown(KeyCode.LeftControl))
StartCrouch();
if (Input.GetKeyUp(KeyCode.LeftControl))
StopCrouch();
}
private void StartCrouch() {
transform.localScale = crouchScale;
transform.position = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z);
if (rb.velocity.magnitude > 0.5f) {
if (grounded) {
rb.AddForce(orientation.transform.forward * slideForce);
}
}
}
private void StopCrouch() {
transform.localScale = playerScale;
transform.position = new Vector3(transform.position.x, transform.position.y + 0.5f, transform.position.z);
}
private void Movement() {
//Extra gravity
rb.AddForce(Vector3.down * Time.deltaTime * 10);
//Find actual velocity relative to where player is looking
Vector2 mag = FindVelRelativeToLook();
float xMag = mag.x, yMag = mag.y;
//Counteract sliding and sloppy movement
CounterMovement(x, y, mag);
//If holding jump && ready to jump, then jump
if (readyToJump && jumping) Jump();
//Set max speed
float maxSpeed = this.maxSpeed;
//If sliding down a ramp, add force down so player stays grounded and also builds speed
if (crouching && grounded && readyToJump) {
rb.AddForce(Vector3.down * Time.deltaTime * 3000);
return;
}
//If speed is larger than maxspeed, cancel out the input so you don't go over max speed
if (x > 0 && xMag > maxSpeed) x = 0;
if (x < 0 && xMag < -maxSpeed) x = 0;
if (y > 0 && yMag > maxSpeed) y = 0;
if (y < 0 && yMag < -maxSpeed) y = 0;
//Some multipliers
float multiplier = 1f, multiplierV = 1f;
// Movement in air
if (!grounded) {
multiplier = 0.5f;
multiplierV = 0.5f;
}
// Movement while sliding
if (grounded && crouching) multiplierV = 0f;
//Apply forces to move player
rb.AddForce(orientation.transform.forward * y * moveSpeed * Time.deltaTime * multiplier * multiplierV);
rb.AddForce(orientation.transform.right * x * moveSpeed * Time.deltaTime * multiplier);
}
private void Jump() {
if (grounded && readyToJump) {
readyToJump = false;
//Add jump forces
rb.AddForce(Vector2.up * jumpForce * 1.5f);
rb.AddForce(normalVector * jumpForce * 0.5f);
//If jumping while falling, reset y velocity.
Vector3 vel = rb.velocity;
if (rb.velocity.y < 0.5f)
rb.velocity = new Vector3(vel.x, 0, vel.z);
else if (rb.velocity.y > 0)
rb.velocity = new Vector3(vel.x, vel.y / 2, vel.z);
Invoke(nameof(ResetJump), jumpCooldown);
}
}
private void ResetJump() {
readyToJump = true;
}
private float desiredX;
private void Look() {
float mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
float mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
//Find current look rotation
Vector3 rot = playerCam.transform.localRotation.eulerAngles;
desiredX = rot.y + mouseX;
//Rotate, and also make sure we dont over- or under-rotate.
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
//Perform the rotations
playerCam.transform.localRotation = Quaternion.Euler(xRotation, desiredX, 0);
orientation.transform.localRotation = Quaternion.Euler(0, desiredX, 0);
}
private void CounterMovement(float x, float y, Vector2 mag) {
if (!grounded || jumping) return;
//Slow down sliding
if (crouching) {
rb.AddForce(moveSpeed * Time.deltaTime * -rb.velocity.normalized * slideCounterMovement);
return;
}
//Counter movement
if (Math.Abs(mag.x) > threshold && Math.Abs(x) < 0.05f || (mag.x < -threshold && x > 0) || (mag.x > threshold && x < 0)) {
rb.AddForce(moveSpeed * orientation.transform.right * Time.deltaTime * -mag.x * counterMovement);
}
if (Math.Abs(mag.y) > threshold && Math.Abs(y) < 0.05f || (mag.y < -threshold && y > 0) || (mag.y > threshold && y < 0)) {
rb.AddForce(moveSpeed * orientation.transform.forward * Time.deltaTime * -mag.y * counterMovement);
}
//Limit diagonal running. This will also cause a full stop if sliding fast and un-crouching, so not optimal.
if (Mathf.Sqrt((Mathf.Pow(rb.velocity.x, 2) + Mathf.Pow(rb.velocity.z, 2))) > maxSpeed) {
float fallspeed = rb.velocity.y;
Vector3 n = rb.velocity.normalized * maxSpeed;
rb.velocity = new Vector3(n.x, fallspeed, n.z);
}
}
/// <summary>
/// Find the velocity relative to where the player is looking
/// Useful for vectors calculations regarding movement and limiting movement
/// </summary>
/// <returns></returns>
public Vector2 FindVelRelativeToLook() {
float lookAngle = orientation.transform.eulerAngles.y;
float moveAngle = Mathf.Atan2(rb.velocity.x, rb.velocity.z) * Mathf.Rad2Deg;
float u = Mathf.DeltaAngle(lookAngle, moveAngle);
float v = 90 - u;
float magnitue = rb.velocity.magnitude;
float yMag = magnitue * Mathf.Cos(u * Mathf.Deg2Rad);
float xMag = magnitue * Mathf.Cos(v * Mathf.Deg2Rad);
return new Vector2(xMag, yMag);
}
private bool IsFloor(Vector3 v) {
float angle = Vector3.Angle(Vector3.up, v);
return angle < maxSlopeAngle;
}
private bool cancellingGrounded;
/// <summary>
/// Handle ground detection
/// </summary>
private void OnCollisionStay(Collision other) {
//Make sure we are only checking for walkable layers
int layer = other.gameObject.layer;
if (whatIsGround != (whatIsGround | (1 << layer))) return;
//Iterate through every collision in a physics update
for (int i = 0; i < other.contactCount; i++) {
Vector3 normal = other.contacts[i].normal;
//FLOOR
if (IsFloor(normal)) {
grounded = true;
cancellingGrounded = false;
normalVector = normal;
CancelInvoke(nameof(StopGrounded));
}
}
//Invoke ground/wall cancel, since we can't check normals with CollisionExit
float delay = 3f;
if (!cancellingGrounded) {
cancellingGrounded = true;
Invoke(nameof(StopGrounded), Time.deltaTime * delay);
}
}
private void StopGrounded() {
grounded = false;
}
}
Thank you in advance.

How do i make it so my character/camera stops moving when UI is open?

I just need to add to it to make the character movement/camera stop moving when the UI is open for the quest, but I don't get where to put the code for the bool variable. And then put to write for the code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class QuestGiver : MonoBehaviour
{
public Quest quest;
public GameObject questWindow;
public Text titleText;
public Text descriptionText;
public Movement2 player;
public void OpenQuestWindow()
{
questWindow.SetActive(true);
titleText.text = quest.title;
descriptionText.text = quest.description;
}
public void AcceptQuest()
{
questWindow.SetActive(false);
quest.isActive = true;
player.quest = quest;
}
void Start()
{
questWindow = GameObject.Find("QuestWindow");
questWindow.SetActive(false);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement2 : MonoBehaviour
{
[SerializeField] CharacterController controller;
private Vector3 playerVelocity;
private bool groundedPlayer;
public float playerSpeed = 5.0f;
private float jumpHeight = 40f;
public float gravityValue = -9.81f;
public Transform Cam;
public KeyCode jump;
public KeyCode FlyUp;
public KeyCode FlyDown;
public bool ablefly;
private float FlyMax = 250f;
public Quest quest;
public int SoulHP = 30;
private void Start()
{
// add character controller
// controller = gameObject.AddComponent<CharacterController>();
}
void Update()
{
// check if the player is grounded and the vector3.y < 0, if one of this condition is true set back the playerVelocity.y = 0f;
groundedPlayer = controller.isGrounded;
if (groundedPlayer && playerVelocity.y < 0)
{
playerVelocity.y = 0f;
}
Vector3 flyup = new Vector3(0, 50, 0);
Vector3 flydown = new Vector3(0, -50, 0);
Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
// Look for the camera y Rotation and multiply it for the vector 3 move in order make the player direction y as same as the camera.
Vector3 FollowCam = Quaternion.Euler(0, Cam.eulerAngles.y, 0) * move;
controller.Move(FollowCam * Time.deltaTime * playerSpeed);
// makes the player jump by adding a float value to the vector 3 y
if (Input.GetKeyDown(jump) && ablefly == false && groundedPlayer == true)
{
playerVelocity.y += 4f;
//print("Diocane");
}
if (Input.GetKeyDown(FlyUp) && ablefly == true)
{
//flyup = Vector3.ClampMagnitude(flyup, 250f);
gravityValue = 0;
controller.Move(flyup * Time.deltaTime * playerSpeed);
}
if (Input.GetKeyDown(FlyDown) && ablefly == true)
{
//flyup = Vector3.ClampMagnitude(flyup, 250f);
gravityValue = 0;
controller.Move(flydown * Time.deltaTime * playerSpeed);
}
playerVelocity.y += gravityValue * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
}
public void GoFind()
{
if (quest.isActive)
{
quest.goal.ItemCollected();
if (quest.goal.IsReached())
SoulHP += 30;
}
}
}
You could set the Time.timeScale to 0 when the ui is opened to make anything using deltaTime stop moving.
In the OpenQuestWindow() you would add Time.timeScale = 0;
and in the AcceptQuest() method add Time.timeScale = 1; to set it back to normal
This looks like a Similar question. please check this and ask me if you don't get that.
EDIT:
This is not a tested code, but I hope will give you an idea, of how to proceed.
1- define a public bool variable mybool in Movement2 script
2- call that bool in the QuestGiver Script like this:
void Start() {
questWindow = GameObject.Find("QuestWindow");
questWindow.SetActive(false);
player.mybool = false; // or get the player gameobject by tag...
}
update your Movement2 update function to this:
void Update() {
if (mybool) {
// check if the player is grounded and the vector3.y < 0, if one of this condition is true set back the playerVelocity.y = 0f;
groundedPlayer = controller.isGrounded;
if (groundedPlayer && playerVelocity.y < 0) {
playerVelocity.y = 0 f;
}
Vector3 flyup = new Vector3(0, 50, 0);
Vector3 flydown = new Vector3(0, -50, 0);
Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
// Look for the camera y Rotation and multiply it for the vector 3 move in order make the player direction y as same as the camera.
Vector3 FollowCam = Quaternion.Euler(0, Cam.eulerAngles.y, 0) * move;
controller.Move(FollowCam * Time.deltaTime * playerSpeed);
// makes the player jump by adding a float value to the vector 3 y
if (Input.GetKeyDown(jump) && ablefly == false && groundedPlayer == true) {
playerVelocity.y += 4 f;
//print("Diocane");
}
if (Input.GetKeyDown(FlyUp) && ablefly == true) {
//flyup = Vector3.ClampMagnitude(flyup, 250f);
gravityValue = 0;
controller.Move(flyup * Time.deltaTime * playerSpeed);
}
if (Input.GetKeyDown(FlyDown) && ablefly == true) {
//flyup = Vector3.ClampMagnitude(flyup, 250f);
gravityValue = 0;
controller.Move(flydown * Time.deltaTime * playerSpeed);
}
playerVelocity.y += gravityValue * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
}
if (!camMove) {
Vector3 move = new Vector3(0, 0, 0);
}
}
Now update that bool in QuestGiver:
public void OpenQuestWindow()
{
questWindow.SetActive(true);
titleText.text = quest.title;
descriptionText.text = quest.description;
player.mybool = false;
}
public void AcceptQuest()
{
questWindow.SetActive(false);
quest.isActive = true;
player.quest = quest;
player.mybool = true;
}

Why isn't the AI following the player?

So I have written some code and everything works in it besides the AI following the player. I don't know what I did wrong so any help would be gladly appreciated!
public class SharkAI : MonoBehaviour
{
public float speed;
public Transform patrolPoints;
private float waitTime;
public float startWaitTime;
public float minX;
public float maxX;
public float minY;
public float maxY;
public float oldPosition;
public float newPosition;
private SpriteRenderer fishes;
public float eyeSightOfFish;
public float disToPlayer;
private Transform player;
// Start is called before the first frame update
void Start()
{
waitTime = startWaitTime;
patrolPoints.position = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
fishes = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void Update()
{
player = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
oldPosition = transform.position.x;
newPosition = patrolPoints.position.x;
Debug.Log("Player distance " + disToPlayer);
//distToPatrolPoint = Vector3.Distance(transform.position, patrolPoints[whichPoint].transform.position);
disToPlayer = Vector2.Distance(transform.position, player.transform.position);
transform.position = Vector2.MoveTowards(transform.position, patrolPoints.position, speed * Time.deltaTime);
if (newPosition > oldPosition)
{
fishes.flipX = true;
}
else { fishes.flipX = false; }
if(disToPlayer <= eyeSightOfFish)
{
transform.position = Vector2.MoveTowards(transform.position, player.position, speed * Time.deltaTime);
}
else if (Vector2.Distance(transform.position, patrolPoints.position) <= 0.2f)
{
if (waitTime <= 0)
{
patrolPoints.position = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
waitTime = startWaitTime;
}
else
{
waitTime -= Time.deltaTime;
}
}
}
}
so im not sure where this is wrong and ive tried a few things but I can't seem to make the ai follow the player.

Rotation smooth in editor but isn't in device

I have a 3D object that I want to rotate with mouse/finger swipe, so I made the script below.
The object's rotation looks smooth on editor, but when playing the game on real device (android), the rotation didn't follow the finger movement immediately, it takes some milliseconds to follow finger, it isn't smooth and the controls become hard and frustrating!
float sensitivity = 0.8f;
Vector2 firstPressPos;
Vector2 secondPressPos;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
//save began touch 2d point
firstPressPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y);
}
if (Input.GetMouseButton(0))
{
//save ended touch 2d point
secondPressPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y);
if (firstPressPos != secondPressPos)
{
float RotX = Input.GetAxis("Mouse X") * sensitivity * Time.deltaTime;
float RotY = Input.GetAxis("Mouse Y") * sensitivity * Time.deltaTime;
transform.RotateAround(Vector3.up, RotX);
transform.RotateAround(Vector3.right, -RotY);
}
}
}
try this code
// Screen Touches
Vector2?[] oldTouchPositions = {
null,
null
};
// Rotation Speed
public float rotSpeed = 0.5f;
public void Update()
{
if (Input.touchCount == 0)
{
oldTouchPositions[0] = null;
oldTouchPositions[1] = null;
}
else if (Input.touchCount == 1)
{
if (oldTouchPositions[0] == null || oldTouchPositions[1] != null)
{
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = null;
}
else
{
Vector2 newTouchPosition = Input.GetTouch(0).position;
float distanceX = (oldTouchPositions[0] - newTouchPosition).Value.x;
float distanceY = (oldTouchPositions[0] - newTouchPosition).Value.y;
float rotX = distanceX * rotSpeed * Mathf.Deg2Rad;
float rotY = distanceY * rotSpeed * Mathf.Deg2Rad;
transform.Rotate(Vector3.up, rotX * 5, Space.Self);
transform.Rotate(Vector3.left, rotY * 5, Space.Self);
oldTouchPositions[0] = newTouchPosition;
}
}
else
{
if (oldTouchPositions[1] == null)
{
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = Input.GetTouch(1).position;
}
else
{
}
}
}
Here's a script I found a few years back that manipulates X axis spin with Mouse or Touches. It seems to work well with touches, but not as good with Mouse. Try it and let me know if it behaves a bit better. This one should adjust the spinning speed dynamically:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpinDrag : MonoBehaviour {
float f_lastX = 0.0f;
float f_difX = 0.5f;
float f_steps = 0.0f;
int i_direction = 1;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
f_difX = 0.0f;
}
else if (Input.GetMouseButton(0))
{
f_difX = Mathf.Abs(f_lastX - Input.GetAxis("Mouse X"));
if (f_lastX < Input.GetAxis("Mouse X"))
{
i_direction = -1;
transform.Rotate(Vector3.up, -f_difX);
}
if (f_lastX > Input.GetAxis("Mouse X"))
{
i_direction = 1;
transform.Rotate(Vector3.up, f_difX);
}
f_lastX = -Input.GetAxis("Mouse X");
}
else
{
if (f_difX > 0.5f) f_difX -= 0.05f;
if (f_difX < 0.5f) f_difX += 0.05f;
transform.Rotate(Vector3.up, f_difX * i_direction);
}
}
}

Unity3D Mecanim Character stopping before turning

so for the past few days I've been working on a character controller in Unity3D using mecanim. It's not based off of my own code, but off of a tutorial I found online, of course that tutorial was meant for Unity 4, so I am running in to small problems here and there, but nothing I couldn't fix up until now.
So the basic problem is that my character seems to (without reason) stop all his momentum and slowly turns around when I try to make a hard 180 degrees turn, afterwards he continues to run like normal again, but I don't see why he would suddenly stop turning.
Here is my character logic script:
using UnityEngine;
using System.Collections;
public class characterLogic : MonoBehaviour {
[SerializeField]
private Animator animator;
[SerializeField]
private FollowCamera gamecam;
[SerializeField]
private float directionSpeed = 1.5f;
[SerializeField]
private float directionDampTime = 0.25f;
[SerializeField]
private float rotationDegreePerSecond = 120f;
[SerializeField]
private float speedDampTime = 0.05f;
private float speed = 0.0f;
private float direction = 0.0f;
private float charAngle = 0f;
private float horizontal = 0.0f;
private float vertical = 0.0f;
private AnimatorStateInfo stateInfo;
private AnimatorTransitionInfo transInfo;
private int m_LocomotionId = 0;
private int m_LocomotionPivotLId = 0;
private int m_LocomotionPivotRId = 0;
private int m_LocomotionPivotLTransId = 0;
private int m_LocomotionPivotRTransId = 0;
public Animator Animator
{
get
{
return this.animator;
}
}
public float Speed
{
get
{
return this.speed;
}
}
public float LocomotionThreshold { get { return 0.2f; } }
// Use this for initialization
void Start () {
animator = GetComponent<Animator>();
if(animator.layerCount >= 2)
{
animator.SetLayerWeight(1, 1);
}
m_LocomotionId = Animator.StringToHash("Base Layer.Locomotion");
m_LocomotionPivotLId = Animator.StringToHash("Base Layer.LocomotionPivotL");
m_LocomotionPivotRId = Animator.StringToHash("Base Layer.LocomotionPivotR");
m_LocomotionPivotLTransId = Animator.StringToHash("Base Layer.Locomotion -> Base Layer.LocomotionPivotL");
m_LocomotionPivotRTransId = Animator.StringToHash("Base Layer.Locomotion -> Base Layer.LocomotionPivotR");
}
public void keysToWorldSpace (Transform root, Transform camera, ref float directionOut, ref float speedOut, ref float angleOut, bool isPivoting){
Vector3 rootDirection = root.forward;
Vector3 keyDirection = new Vector3 (horizontal, 0, vertical);
speedOut = keyDirection.sqrMagnitude;
//get camera rotation
Vector3 cameraDirection = camera.forward;
cameraDirection.y = 0.0f;
Quaternion referentialShift = Quaternion.FromToRotation (Vector3.forward, cameraDirection);
//convert key input to world space coordinates
Vector3 moveDirection = referentialShift * keyDirection;
Vector3 axisSign = Vector3.Cross (moveDirection, rootDirection);
Debug.DrawRay (new Vector3(root.position.x, root.position.y + 2f, root.position.z), moveDirection, Color.green);
Debug.DrawRay (new Vector3(root.position.x, root.position.y + 2f, root.position.z), axisSign, Color.red);
Debug.DrawRay (new Vector3(root.position.x, root.position.y + 2f, root.position.z), rootDirection, Color.magenta);
Debug.DrawRay (new Vector3(root.position.x, root.position.y + 2f, root.position.z), keyDirection, Color.blue);
float angleRootToMove = Vector3.Angle(rootDirection, moveDirection) * (axisSign.y >= 0 ? -1f : 1f);
if (!isPivoting)
{
angleOut = angleRootToMove;
}
angleRootToMove /= 180f;
directionOut = angleRootToMove * directionSpeed;
}
// Update is called once per frame
void Update () {
if (animator) {
stateInfo = animator.GetCurrentAnimatorStateInfo(0);
transInfo = animator.GetAnimatorTransitionInfo(0);
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
charAngle = 0f;
direction = 0f;
keysToWorldSpace (this.transform, gamecam.transform, ref direction, ref speed, ref charAngle, isInPivot());
animator.SetFloat ("Speed", speed);
animator.SetFloat ("Direction", direction, directionDampTime, Time.deltaTime);
if(speed > LocomotionThreshold){
if(!isInPivot()){
Animator.SetFloat("Angle", charAngle);
}
}
if(speed < LocomotionThreshold && Mathf.Abs(horizontal) < 0.05f){
animator.SetFloat("Direction", 0f);
animator.SetFloat("Speed", speed, speedDampTime, Time.deltaTime);
}
Debug.Log(Speed);
Debug.Log(charAngle);
}
}
void FixedUpdate() {
if (IsInLocomotion () && ((direction >= 0 && horizontal >= 0) || (direction < 0 && horizontal < 0))) {
Vector3 rotationAmount = Vector3.Lerp(Vector3.zero, new Vector3(0f, rotationDegreePerSecond * (horizontal < 0f ? -1f : 1f), 0f), Mathf.Abs(horizontal));
Quaternion deltaRotation = Quaternion.Euler(rotationAmount * Time.deltaTime);
this.transform.rotation = (this.transform.rotation * deltaRotation);
}
}
public bool isInPivot(){
return stateInfo.fullPathHash == m_LocomotionPivotLId ||
stateInfo.fullPathHash == m_LocomotionPivotRId ||
transInfo.nameHash == m_LocomotionPivotLTransId ||
transInfo.nameHash == m_LocomotionPivotRTransId;
}
public bool IsInLocomotion(){
return stateInfo.fullPathHash == m_LocomotionId;
}
}
I believe it either has to do something with this script or with the transitions within mecanim. I also ported the finished product (found here: https://github.com/jm991/UnityThirdPersonTutorial ) of the tutorial over to Unity 5 and didn't experience the same problem there, I am not entirely sure what the difference is which gives me this problem, but if any of you know or find out, please let me know.
I found the problem myself already!
Here is the new code in case anyone is interested in the future:
using UnityEngine;
using System.Collections;
public class characterLogic : MonoBehaviour {
[SerializeField]
private Animator animator;
[SerializeField]
private FollowCamera gamecam;
[SerializeField]
private float directionSpeed = 1.5f;
[SerializeField]
private float directionDampTime = 0.25f;
[SerializeField]
private float rotationDegreePerSecond = 120f;
[SerializeField]
private float speedDampTime = 0.05f;
[SerializeField]
private float fovDampTime = 3f;
private float horizontal = 0.0f;
private float vertical = 0.0f;
private float speed = 0.0f;
private float direction = 0.0f;
private float charAngle = 0f;
private const float SPRINT_SPEED = 2.0f;
private const float SPRINT_FOV = 75.0f;
private const float NORMAL_FOV = 60.0f;
private const float WALK_SPEED = 0.1f;
private AnimatorStateInfo stateInfo;
private AnimatorTransitionInfo transInfo;
private int m_LocomotionId = 0;
private int m_LocomotionPivotLId = 0;
private int m_LocomotionPivotRId = 0;
private int m_LocomotionPivotLTransId = 0;
private int m_LocomotionPivotRTransId = 0;
public Animator Animator
{
get
{
return this.animator;
}
}
public float Speed
{
get
{
return this.speed;
}
}
public float LocomotionThreshold { get { return 0.2f; } }
// Use this for initialization
void Start () {
animator = GetComponent<Animator>();
if(animator.layerCount >= 2)
{
animator.SetLayerWeight(1, 1);
}
m_LocomotionId = Animator.StringToHash("Base Layer.Locomotion");
m_LocomotionPivotLId = Animator.StringToHash("Base Layer.LocomotionPivotL");
m_LocomotionPivotRId = Animator.StringToHash("Base Layer.LocomotionPivotR");
m_LocomotionPivotLTransId = Animator.StringToHash("Base Layer.Locomotion -> Base Layer.LocomotionPivotL");
m_LocomotionPivotRTransId = Animator.StringToHash("Base Layer.Locomotion -> Base Layer.LocomotionPivotR");
}
public void keysToWorldSpace (Transform root, Transform camera, ref float directionOut, ref float speedOut, ref float angleOut, bool isPivoting){
Vector3 rootDirection = root.forward;
Vector3 keyDirection = new Vector3 (horizontal, 0, vertical);
speedOut = keyDirection.sqrMagnitude;
//get camera rotation
Vector3 cameraDirection = camera.forward;
cameraDirection.y = 0.0f;
Quaternion referentialShift = Quaternion.FromToRotation(Vector3.forward, Vector3.Normalize(cameraDirection));
//convert key input to world space coordinates
Vector3 moveDirection = referentialShift * keyDirection;
Vector3 axisSign = Vector3.Cross (moveDirection, rootDirection);
Debug.DrawRay (new Vector3(root.position.x, root.position.y + 2f, root.position.z), moveDirection, Color.green);
Debug.DrawRay (new Vector3(root.position.x, root.position.y + 2f, root.position.z), axisSign, Color.red);
Debug.DrawRay (new Vector3(root.position.x, root.position.y + 2f, root.position.z), rootDirection, Color.magenta);
Debug.DrawRay (new Vector3(root.position.x, root.position.y + 2f, root.position.z), keyDirection, Color.blue);
float angleRootToMove = Vector3.Angle(rootDirection, moveDirection) * (axisSign.y >= 0 ? -1f : 1f);
if (!isPivoting)
{
angleOut = angleRootToMove;
}
angleRootToMove /= 180f;
directionOut = angleRootToMove * directionSpeed;
}
// Update is called once per frame
void Update () {
if (animator) {
stateInfo = animator.GetCurrentAnimatorStateInfo(0);
transInfo = animator.GetAnimatorTransitionInfo(0);
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
charAngle = 0f;
direction = 0f;
float charSpeed = 0f;
keysToWorldSpace (this.transform, gamecam.transform, ref direction, ref charSpeed, ref charAngle, isInPivot());
if (Input.GetButton("Sprint"))
{
speed = Mathf.Lerp(speed, SPRINT_SPEED, Time.deltaTime);
gamecam.GetComponent<Camera>().fieldOfView = Mathf.Lerp(gamecam.GetComponent<Camera>().fieldOfView, SPRINT_FOV, fovDampTime * Time.deltaTime);
}
else
{
speed = charSpeed;
gamecam.GetComponent<Camera>().fieldOfView = Mathf.Lerp(gamecam.GetComponent<Camera>().fieldOfView, NORMAL_FOV, fovDampTime * Time.deltaTime);
}
if (Input.GetButton("Walk"))
{
speed = Mathf.Lerp(speed, WALK_SPEED, Time.deltaTime);
}
else
{
speed = charSpeed;
}
animator.SetFloat("Speed", speed, speedDampTime, Time.deltaTime);
animator.SetFloat("Direction", direction, directionDampTime, Time.deltaTime);
if(speed > LocomotionThreshold){
if(!isInPivot()){
Animator.SetFloat("Angle", charAngle);
}
}
if(speed < LocomotionThreshold && Mathf.Abs(horizontal) < 0.05f){
animator.SetFloat("Direction", 0f);
animator.SetFloat("Speed", speed, speedDampTime, Time.deltaTime);
}
Debug.Log(Speed);
Debug.Log(charAngle);
}
}
void FixedUpdate() {
if (IsInLocomotion () && ((direction >= 0 && horizontal >= 0) || (direction < 0 && horizontal < 0))) {
Vector3 rotationAmount = Vector3.Lerp(Vector3.zero, new Vector3(0f, rotationDegreePerSecond * (horizontal < 0f ? -1f : 1f), 0f), Mathf.Abs(horizontal));
Quaternion deltaRotation = Quaternion.Euler(rotationAmount * Time.deltaTime);
this.transform.rotation = (this.transform.rotation * deltaRotation);
}
}
public bool isInPivot(){
return stateInfo.fullPathHash == m_LocomotionPivotLId ||
stateInfo.fullPathHash == m_LocomotionPivotRId ||
transInfo.nameHash == m_LocomotionPivotLTransId ||
transInfo.nameHash == m_LocomotionPivotRTransId;
}
public bool IsInLocomotion(){
return stateInfo.fullPathHash == m_LocomotionId;
}
}
It turned out that the guy who made the original code was using a dampTime on his speed due to which he wouldn't instantly stand still if he'd let go off a button. It's something he hadn't explained in his tutorial yet, so I must have missed it. Anyways I hope this might help anyone in the future with a similar problem.

Categories

Resources