Im trying to get a slow motion on the game im making but it looks realy laggy. Im using the FPS controller from the standard assets given by unity.I attached this script to it :
function Update ()
{
if (Input.GetKeyDown ("q"))
{
Time.timeScale = 0.5;
}
if (Input.GetKeyDown ("e"))
{
Time.timeScale = 2.0;
}
if (Input.GetKeyDown ("t"))
{
Time.timeScale = 1.0;
}
}
I know this is a similar question to this one http://answers.unity3d.com/questions/39279/how-to-get-smooth-slow-motion.html
but the fixes given on that question won't work.I tried adding a rigidbody to it and putting the Interpolation to Interpolate but it doesn't do anything.(I removed the tick from "Use Gravity" because the character started flying).Im new in unity and scripting so please go easy on me.
Thank you.
You should change Time.fixedDeltaTime as well:
function Update () {
if (Input.GetKeyDown ("q")){
Time.timeScale = 0.5;
Time.fixedDeltaTime = 0.02F * Time.timeScale;
}
}
To return it to normal motion again you should call these two lines
Time.timeScale = 1;
Time.fixedDeltaTime = 0.02F * Time.timeScale;
You just need to call SetTimeScale Method as target timescale as argument :)
using UnityEngine;
public class TimeScaleSmooth : MonoBehaviour
{
public float targetTimeScale = 1;
public float speed = 1;
void Update()
{
Time.timeScale = Mathf.MoveTowards(Time.timeScale, targetTimeScale,
Time.unscaledDeltaTime * speed);
//0.02 is default fixedDeltaTime
Time.fixedDeltaTime = timeScale * 0.02f;
//FOR TEST
if (Input.GetKeyDown(KeyCode.A))
{
SetTimeScale(1);
}
if (Input.GetKeyDown(KeyCode.S))
{
SetTimeScale(0.2f);
}
}
public void SetTimeScale(float timeScale)
{
targetTimeScale = timeScale;
}
}
Note that we used Time.unscaledDeltaTime which is independent of timescale.
You can tweak transition time using speed.
This is actually insanely easy. In fact, you don't even have to code anything! Just go into every rigidbody in the scene, and change the interpolation mode to "interpolate" or "extrapolate". They mean very different things, but both have the end result of perfectly smooth slow-motion.
Related
So in my game you are a sphere rolling down ramps, but if you go too fast and crash into a ledge the game freezes and the console gets spammed with the first error in the title followed by the second one. I managed to find what line of code caused this problem, here's that script:
public class FöljaBoll : MonoBehaviour
{
public GameObject player;
public float yOffset;
public float zOffset;
Transform playerPosition;
Transform cameraPosition;
// Start is called before the first frame update
void Start()
{
playerPosition = player.GetComponent<Transform>();
cameraPosition = gameObject.GetComponent<Transform>();
}
// Update is called once per frame
void Update()
{
if (playerPosition == null)
{
return;
}
cameraPosition.position = playerPosition.position + new Vector3(0, +yOffset, -zOffset);
}
private void FixedUpdate()
{
if (player == null)
{
return;
}
else
{
float speed = player.GetComponent<Rigidbody>().velocity.z + 6;
float targetFOV = (float)Math.Log(speed, 1.1) + 34;
GetComponent<Camera>().fieldOfView = Mathf.Lerp(GetComponent<Camera>().fieldOfView, targetFOV, (float)0.1);
}
}
}
So what it does is it sets the FOV based on the player speed through a logarithmic function in order for it to not get out of control at high speeds, but for some reason this part (I commented it out and wasn't able to recreate the errors):
GetComponent<Camera>().fieldOfView = Mathf.Lerp(GetComponent<Camera>().fieldOfView, targetFOV, (float)0.1);
triggers the error messages. If anyone could help me out here that would be awesome, thanks in advance! :)
I solved it myself by setting the bounciness of the Physics Material attached to both the ramps and the sphere to 0. This post: https://answers.unity.com/questions/9985/limiting-rigidbody-velocity.html said that bounciness combined with high velocities can cause problems and that seems to have been the problem.
Here is my character controller code.
public float speed;
float Velocity;
public float jump;
void Update ()
{
Velocity = 0;
if (Input.GetKey (KeyCode.LeftArrow) || Input.GetKey (KeyCode.A))
{
Velocity = -speed;
}
if (Input.GetKey (KeyCode.RightArrow) || Input.GetKey (KeyCode.D))
{
Velocity = speed;
}
if (Input.GetKey (KeyCode.UpArrow) || Input.GetKey("space") || Input.GetKey (KeyCode.W))
{
GetComponent<Rigidbody2D> ().velocity = new Vector2 (GetComponent<Rigidbody2D> ().velocity.x,
jump);
}
GetComponent<Rigidbody2D> ().velocity = new Vector2 (moveVelocity, GetComponent<Rigidbody2D>
().velocity.y);
}
}
This is a very simple movement code
here is my cam follow code i got from Brackeys
I am having an infinte jump problem with the code and i do not know what to do to fix it
I do not know the correct syntax yet to stop it.
I am using Unity 2019.4.2f1 and VScode 2020.
Im not sure if adding what versions I use will help
but I am always getting compiler errors saying that stuff does not exist in the current context but i do not know anything else that does exist in the current context that will work.
void Update()
{
transform.position = playerPos.position + offset;
}
To fix infinite jump, use Input.GetKeyDown(KeyCode.UpArrow) instead of Input.GetKey(KeyCode.UpArrow). The GetKey function is for checking when a key is held down. the GetKeyDown function is for getting the first time the key is pressed.
Alright, so I'm using a coroutine to wait 6 seconds before executing a method to change a float in an animator, really simple stuff. My issue is that something in this script is causing my unity editor to completely lock up when I place it on a gameobject, and I don't know why. I don't think I have any infinite loops going, but I'm not sure. Anyone have any ideas? thx ahead of time.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class handanimatordock : MonoBehaviour
{
public Animator hand;
private float Blendfloat;
bool ChangeHand = false;
private float timefloat = 0.0f;
// Start is called before the first frame update
void Start()
{
StartCoroutine(waiter());
}
// Update is called once per frame
void Update()
{
}
public void changeHands()
{
if (ChangeHand == false)
{
ChangeHand = true;
while (Blendfloat != 1.0f)
{
Blendfloat = Blendfloat + 0.01f;
hand.SetFloat("Blend", Blendfloat);
}
}
else
{
ChangeHand = false;
while (Blendfloat != 0.0f)
{
Blendfloat = Blendfloat - 0.01f;
hand.SetFloat("Blend", Blendfloat);
}
}
}
IEnumerator waiter()
{
//Wait for 4 seconds
yield return new WaitForSeconds(6);
changeHands();
StartCoroutine(waiter());
}
}
You probably have an infinite loop in
while (Blendfloat != 1.0f)
{
Blendfloat = Blendfloat + 0.01f;
hand.SetFloat("Blend", Blendfloat);
}
Never directly compare two float values using == or !=.
Due to floating point impression a value like
10f * 0.1f
might end up being 1.000000001 or 0.99999999 though logically you would expect exactly 1. So your condition is probably never false!
Usually you rather give it a certain range like e.g.
while(Mathf.Abs(Blendfloat - 1) > certainThreshold)
Unity has for that Mathf.Approximately
while(!Mathf.Approximately(Blendfloat, 1f)
which basically equals comparing to a threshold of Mathf.Epsilon
which(Math.Abs(Blendfloat - 1) > Mathf.Epsilon)
Note that anyway what you have right now will execute the entire loop in one single frame.
If you really wanted it to fade over time you need to do one iteration per frame in e.g. a Coroutine!
I want my enemy to move back to starting position. He follows me until I get out of his range and then he just stops.
Also i want my skeleton to stop for like 5 sec, and then go back to starting point, any ideas ? I never did anything involving time, exept stopping it.
Here is my script for enemy:
Also here is a screenshoot of inspector on the skeleton: enemy
Here is my script for enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class chase : MonoBehaviour
{
public Transform player;
private Animator anim;
public float LookRadius = 15f;
public Transform enemyStartPos;
// Use this for initialization
void Start()
{
anim = GetComponent<Animator>();
this.enemyStartPos.position = this.transform.position;
}
// Update is called once per frame
void Update()
{
if (!PauseMenu.GameIsPaused)
{
if (Vector3.Distance(player.position, this.transform.position) < 15)
{
Vector3 direction = player.position - this.transform.position;
direction.y = 0;
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);
anim.SetBool("isIdle", false);
if (direction.magnitude > 3)
{
this.transform.Translate(0, 0, 0.05f);
anim.SetBool("isWalking", true);
anim.SetBool("isAttacking", false);
}
else
{
anim.SetBool("isAttacking", true);
anim.SetBool("isWalking", false);
}
}
else
{
if (Vector3.Distance(this.enemyStartPos.position, this.transform.position) >1)
{
Vector3 direction = this.enemyStartPos.position - this.transform.position;
direction.y = 0;
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);
anim.SetBool("isIdle", false);
if (direction.magnitude > 1)
{
this.transform.Translate(0, 0, 0.05f);
anim.SetBool("isWalking", true);
anim.SetBool("isAttacking", false);
}
}
else
anim.SetBool("isIdle", true);
anim.SetBool("isAttacking", false);
anim.SetBool("isWalking", false);
}
}
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, LookRadius);
}
}
Before you try to "code" this, think about it in terms of your program design. You have designed and implemented behavior that says "if the bot's position is within X units of the player's position, turn the bot and move it toward the player."
What you describe wanting to do next can be thought of in the same way (which should lead to similar code).. "else, if the bot's position is NOT within X units of the player's position, turn the bot and move it toward [origin]." Note, this means you need to define what [origin] is for the bot. Point being, it makes no difference in the code whether you are moving toward a player or some arbitrary fixed point. The code to move one transform toward another transform is the same.
For "wandering" it's essentially the same thought process: If bot is within X units of [origin] and not following player, pick a random direction and move that way. (better yet, pick a random direction and move that way for some amount of time so your bot doesn't just jitter around origin).
I have a ball standing on a platform and i have written code so that every time i swipe up the ball jumps from one platform to another depending on the force of the swipe. At the moment my platforms are just placed in position by myself and i dont have a script for their random generation. The only script i have is on the player for swiping and moving forward.
Currently im making this motion by adding force in two directions, up and forward to create the projectile motion. Its working like its supposed too, but the motion is too slow. I want it to sort of move faster. Iwe tried playing with the forces as well as the mass of the ball. They do make a difference, but I still want the ball to move some what faster.
Is adding force the best way to do this? Or would you recommend a different way?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SwipeScript : MonoBehaviour {
public float maxTime;
public float minSwipeDist;
float startTime;
float endTime;
Vector3 startPos;
Vector3 endPos;
float swipeDistance;
float swipeTime;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
startTime = Time.time;
startPos = touch.position;
}
else if (touch.phase == TouchPhase.Ended)
{
endTime = Time.time;
endPos = touch.position;
swipeDistance = (endPos - startPos).magnitude;
swipeTime = endTime - startTime;
if (swipeTime < maxTime && swipeDistance > minSwipeDist)
{
swipe();
}
}
}
}
public void swipe()
{
Vector2 distance = endPos - startPos;
if (Mathf.Abs(distance.y) > Mathf.Abs(distance.x))
{
Debug.Log("Swipe up detected");
jump();
}
}
private void jump()
{
Vector2 distance = endPos - startPos;
GetComponent<Rigidbody>().AddForce(new Vector3(0, Mathf.Abs(distance.y/5), Mathf.Abs(distance.y/5)));
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == "Cube (1)") {
Debug.Log("collision!");
GetComponent<Rigidbody>().velocity = Vector3.zero;
GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
}
}
}
I was writing my answer when I noticed #Fredrik comment: pretty much all he said was in what I wrote so I'll just skip it ! (I also do not recommend increasing Time.timeScale)
The other way you could move your ball would be using ballistic equations and setting your RigidBody to Kinematic. This way you will be able to control the ball speed through code using RigidBody.MovePosition() and still get OnCollision[...] events.
Also as a side note I do not recommend using collision.gameObject.name for collision object checking but rather tagging your cubes or even setting their layer to a specific one (but I guess this may be temporary code of yours ;) ).
Hope this helps,
Either pass ForceMode.VelocityChange as a second parameter to AddForce, or make sure you divide your vector by Time.fixedDeltaTime (which has the effect of multiplying it because Time.fixedDeltaTime will be less than 1).