I am trying to slow down and ultimately stop it, i have a script that slows down timeScale however with that my player using mecanim also slows down.
I have created a TimeController.cs
that will allow me to keep track of time by having a alternative deltaTime as the player can use for variable,
public class TimeController : MonoBehaviour {
private float oldTimeSinceStart;
public float deltaTime;
void LateUpdate () {
float timeSinceStart = Time.realtimeSinceStartup;
deltaTime = timeSinceStart - oldTimeSinceStart;
oldTimeSinceStart = timeSinceStart;
if (Input.GetButton("BulletTime"))
{
if (Time.timeScale > 0.01)
{
Time.timeScale -= 0.004f;
}
}
else
{
if (Time.timeScale < 1)
{
Time.timeScale += 0.01f;
}
}
}
}
From this point i thought about using Animator Update to set the mecanim logic driven speed for player speed and animation speed, however i dont seem to be able,
When using Animator.Update(MyTimeController.deltaTime);
It seems to run at variable speed, as if the Animator has a second input somewhere.
is there away around this? can you isolate the timeScale from the player/mecanim and have it look at another Time class for input variables?
So time slows down for the world but not the player, think clockstoppers!
As Felype mentioned, you can use Animator Component, I usually get the Animator component and then use <animator_object>[<animation_clip_object.name>].speed. For speed, value of 1 means normal speed.
Acording to Unity Documentation there's this animation speed property in the animator object:
https://docs.unity3d.com/Documentation/ScriptReference/Animator-speed.html
Try using
<yourgameobjecthere>.getComponent<Animator>().speed = Time.timescale; right after you set the time scale.
I'm not sure the animation speed is applied correctly during an animation tho.
Related
I'm making a 3D Side-Scroll Platformer Game,
I have trouble with my character when it steps on the moving platform it will not come along on the platform. I want my character to stay on the moving platform so I think converting my Character Controller into Rigibody will help me,
I need help to give me ideas on how I can reuse my Character Controller Script in Rigibody. This is my code, how can I reuse this in Rigibody script?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public CharacterController controller;
private Vector3 direction;
public float speed = 8;
public float jumpForce = 30;
public float gravity = -20;
public Transform groundCheck;
public LayerMask groundLayer;
public bool ableToMakeADoubleJump = true;
public Animator animator;
public Transform model;
void Start()
{
}
// Update is called once per frame
void Update()
{
if (PlayerManager.gameOver)
{
//play death animation
animator.SetTrigger("die");
//disable the script
this.enabled = false;
}
float hInput = Input.GetAxis("Horizontal");
direction.x = hInput * speed;
animator.SetFloat("speed", Mathf.Abs(hInput));
bool isGrounded = Physics.CheckSphere(groundCheck.position, 0.15f, groundLayer);
animator.SetBool("isGrounded", isGrounded);
if (isGrounded)
{
//Jump Codes
ableToMakeADoubleJump = true;
if (Input.GetButtonDown("Jump"))
{
Jump();
}
}
else
{
direction.y += gravity * Time.deltaTime;
if (ableToMakeADoubleJump & Input.GetButtonDown("Jump"))
{
DoubleJump();
}
}
if (hInput != 0)
{
Quaternion newRoattion = Quaternion.LookRotation(new Vector3(hInput, 0, 0));
model.rotation = newRoattion;
}
//Move the player using the character controller
controller.Move(direction * Time.deltaTime);
}
private void DoubleJump()
{
//Double Jump Codes
animator.SetTrigger("doubleJump");
direction.y = jumpForce;
ableToMakeADoubleJump = false;
}
private void Jump()
{
direction.y = jumpForce;
}
}
I would not recommend switching between the two. It would get tricky, and think about it, you are alternating between two very different things. One is movement and one is physics.
However, I would reccomend adding to your current script so that the player would move with the moving platform.
There is a lot of stuff in this answer, so read the whole thing.
Btw, when I talk about velocity, in your case it is direction.
Since it seems like you know how to code pretty well, I won’t write out the script, rather tell you some physics ideas to get you going in the right direction.
The reason people can stand on a moving platform and not fall off is because of friction.
If you are standing on a gameObject with enough friction (you could add a physics material the gameObject you stand on and change friction there. Note that physics materials only work with rigidbodies, but you might want to use it to just read the value)
First of all, you are going to want to raycast down to obtain the object you are standing on. From there you can get the physics material from hit.collider.sharedMaterial (or any other hit. to obtain data about what object you are standing on.
If they friction is too low, just make the character slip off, like it was before (I assume)
If the friction is above a threshold, get the velocity from the object you are standing on. If it was a rigidbody, hit.rigidbody.velocity. If it is controlled by script, use hit.collider.gameObject.GetComponent<scriptname>().velocityvariablename This part is continued later on
This is not necessary but useful: You can think of this as grabbing on a rope. When you are grabbing on a slippery rope, and someone pulls it (Like tug of war), You won’t move because the rope will slide through your hands. If the rope had grip tape on it and someone pulled it, you would come with it because it has more friction. You can think of the platform the same way. Now on to the more complex part: When you grip a rope that is stationary, and someone pulls it, you come with it as its velocity changes. When the rope is already being pulled, so its velocity is not stationary and it is already something. You grab onto it and a similar thing happens. It is like you are becoming a part of that rope. Similar to how if you are running, the arms and legs and head is a part of you. If you lose grip, you are no longer a part of that body, like your arms falling off when running. In other words, you become part of the body when you attach yourself to it.
Bottom line:
Get the velocity of the platform and set platformVel to it, do not add that to velocity, rather do a seperate controller.Move(platformVel).
A small customization:
Vector3.Lerp the platformVel to 0, so it doesn’t change while on the platform, but gradually goes to (0,0,0) when you get off. This way, there is a little momentum maintained from standing on the platform.
Feel free to ask anything in the comments.
Trying to create simple endless moving platform with 3 cubes of scale 70 on z(Player will not move forward, will just move left/right). The RepositionPlatform script is attached to each platform/cube which is responsible for movement and checks the z position of each platform and if it is <= -100.0f, then position is changed to (0,0,200.0f).
Problem is sometimes there is a little gap between the platforms(cubes) or there is a little overlap which I don't want.
Platforms should be placed one after each other without any gap or overlap!!!
Can anyone help find the issue looking at the script or suggest any other better way ?
The script below is attached to 3 platform game objects!!!
public class RepositionPlatform : MonoBehaviour
{
private GameObject platformGO;
[SerializeField]
private float speed;
// Start is called before the first frame update
void Start()
{
platformGO = this.gameObject;
Debug.Log("In RepositionPlatform Start method - "+ platformGO.name);
}
// Update is called once per frame
void Update()
{
Debug.Log("In RepositionPlatform Update Method- " + platformGO.name);
platformGO.transform.Translate(Vector3.back * Time.deltaTime * speed);
Transform platformTransform = platformGO.transform;
if(platformTransform.position.z <= -100.0f)
{
platformTransform.position = new Vector3(0,0,200.0f);
}
}
}
Probably because speed is a floating point value. You should read up on them if you haven't already.
Long story short, you aren't accounting for how far below -100 the value might have gone, you're just resetting it.
If you translate it instead, you will preserve any extra distance beyond -100 that the transform might have gone.
Try this instead:
If (transform.position.z < -100){
transform.Translate(new Vector3(0,0,200));
}
Edit
Should be Z value, not X
I have just updated Unity to version 5.2.1 from 5.0.0 this morning and I experienced a few problems. After Unity translated the game to work for the new version, I tested the game. Everything worked fine, except that when I shot a bullet in my game, they would stick to the walls instead of bouncing off of them, but only at certain angles and distances. It was like the bullet was so fast that it skipped hitting the collider and got stuck inside of the collider. That would make a little bit of sense, but the weird part is that I have a C# script for slow motion in the game. Whenever I turn the slow motion on and then turn it off again, the problem with bullets sticking goes away. I cannot seem to figure out what is causing the problem and it definitely wasn't there before I updated the software. Can anyone help me out with this? Thanks. I'll post the bullet script and the slow motion script below. The bullet is instantiated inside the player script by the way.
Bullet Script:
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour {
public float bulletSpeed;
public float bulletOpacity;
public bool fadeOut;
Animator anim;
Rigidbody2D rigidbod;
SpriteRenderer spriterend;
public GameObject player;
public float aimRotation;
// Use this for initialization
void Start () {
anim = GetComponent<Animator> ();
rigidbod = GetComponent<Rigidbody2D> ();
spriterend = GetComponent<SpriteRenderer> ();
rigidbod.velocity = transform.right * bulletSpeed;
rigidbod.gravityScale = 0;
bulletOpacity = 1;
}
// Update is called once per frame
void Update () {
Destroy (gameObject, 3f);
spriterend.color = new Color (1f, 1f, 1f, bulletOpacity);
if (fadeOut == true)
bulletOpacity -= 0.03f;
if (bulletOpacity <= 0)
Destroy (gameObject);
aimRotation = player.GetComponent<Player> ().aimRotation;
}
void OnTriggerEnter2D (Collider2D bulletHit) {
/*if (bulletHit.gameObject.layer == LayerMask.NameToLayer ("vulnerableLayer")) {
}*/
rigidbod.gravityScale = 1;
rigidbod.drag = 1;
fadeOut = true;
}
}
Slow Motion Script:
using UnityEngine;
using System.Collections;
public class SlowMotion : MonoBehaviour {
public float currentLongevity = 0f;
public float slowAmount = 0.2f;
public float normalTime = 1f;
public float slowLongevity = 0.4f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown (1)) {
Time.fixedDeltaTime = 0.0f * Time.timeScale;
if (Time.timeScale == normalTime)
Time.timeScale = slowAmount;
}
if (Time.timeScale == slowAmount) {
currentLongevity += Time.deltaTime;
}
if (currentLongevity > slowLongevity) {
currentLongevity = 0;
Time.timeScale = normalTime;
}
}
}
Since you indicated that the 'weird' bullet behavior ceases after the SlowMotion script is run, I would suggest that the issue has to do with setting Time.fixedDeltaTime as you are doing in the Update() method of the SlowMotion script. This is also supported by your later comment that the 'weird' behavior no longer appears when you set the rigidBody2D's collision detection to continuous (the bullet's RigidBody2D I assume).
Continuous RididBody2D collision detection enables determining if contact occurred between updates, where as Discrete collision detection registers a collision during a physics update. In your SlowMotion script, the following line (in the Update() method) sets fixedDeltaTime to zero:
Time.fixedDeltaTime = 0.0f * Time.timeScale;
Since Time.fixedDeltaTime is the interval in seconds at which physics and other fixed frame rate updates are performed, there must be some minimum value at which the frame rate is realistically run, (0.0 cannot be an actual frame-rate update interval). When Time.fixedDeltaTime == 0.0, Unity may use a default minimum value or use this to indicate that frame updates run as often as possible, (though I have not tested this). Since the Bullet script calls Update() rather than FixedUpdate(), there is no guarantee that the actual interval between the frame updates is uniform. I suspect that when you run the SlowMotion script, and set Time.fixedDeltaTime to 0.0, Unity runs with the smallest possible frame update interval and following this, it does render the expected bullet behavior.
One way to test this would be to set your initial Time.fixedDeltaTime to 0.0 in the editor (and your collision detection behavior back to discrete for the bullet's RididBody2D).
To set Time Manager fixedDeltaTime in the editor: main menu -> Edit -> Project Settings -> Time
If you find a fixedDeltaTime that works, you can set this in the editor and retrieve the initial value in your SlowMotion script in the Awake() method to initialize the base fixedDeltaTime. I would not recommend using fixedDeltaTime == 0.0 since there is no indication in the documentation of a consistent behavior for a time interval of 0.0 and it may be bound more to the underlying hardware and could result in more unexpected behavior.
Hope this helps, cheers!
I've been working on this script for the past day. For some reason my character will not jump as long as it's animator is active. I've got into the animation (there is only one) and removed all references to the animation placing a position anywhere and still the issue presides.
I have discovered that I can make my player jump if I use Co-routine which I'm using. However, I'm still new to using them and I can't work out why my player won't fall to the ground once a force has been added to it. And my player only moves up when the button is clicked. Could someone please take a look at my script and tell me what I'm doing wrong?
public float jumpSpeed = 100.0f;
public float jumpHeight = 2.0f;
public AudioClip jumpSound;
private GameObject pos;
private bool moving;
private bool isJumping;
void Start()
{
}
// Update is called once per frame
void Update ()
{
if(Input.GetMouseButtonDown(0))// && !moving)
{
isJumping = true;
StartCoroutine(JumpPlayer(gameObject.transform.localPosition));
}
else
{
isJumping = false;
}
}
IEnumerator JumpPlayer(Vector3 startPos)
{
Vector3 jump = new Vector3(transform.localPosition.x, jumpHeight, transform.localPosition.z);
float t = 0f;
t += Time.deltaTime / jumpSpeed;
rigidbody.AddForce(Vector3.up * jumpSpeed);
//gameObject.transform.localPosition = Vector3.Lerp(startPos, jump, 0.5f);
//isJumping = false;
yield return null;
}
Firstly, your use of coroutine isn't doing anything in particular - because it only does yield return null at the end, it'll run in a single frame and then exit. You could make it a regular void function and you shouldn't see any change in behaviour.
Removing other redundant code and you have just this:
if(Input.GetMouseButtonDown(0))
{
rigidbody.AddForce(Vector3.up * jumpSpeed);
}
This force is added for only a single frame: the frame where the mouse button is pressed down (if you used Input.GetMouseButton instead, you'd see the force applied for multiple frames).
You say "my player only moves up when the button is clicked" but I'm not clear why that's a problem - perhaps you mean that the player should continue to move up for as long as the button is held, in which case you should refer to my previous paragraph.
The most obvious reasons for the player not falling again are related to the RigidBody component: do you have weight & drag set to suitable values? An easy way to test this would be to position your player some distance from the ground at the start of the scene, and ensure that they fall to the ground when you start the scene.
Another reason might be that you're using the default override of .AddForce in an Update cycle. The default behaviour of this method applies force during the FixedUpdate calls, and you might find that using ForceMode.Impulse or ForceMode.VelocityChange gives you the result you're looking for.
hi i was wondering if someone could help me fix practice code (i make practice codes before i make the real thing because its just how i roll) it is basically an object that requires the user to click on the screen in order for it to not touch the ground much like flappy bird however although i have applied gravity correctly to the sprite i cannot fix the velocity section (i coded is to every time the user clicks with his mouse or taps the space key the object will move up like flappy bird)
using UnityEngine;
using System.Collections;
public class BirdMovment : MonoBehaviour {
Vector3 Velocity = Vector3.zero;
public Vector3 gravity;
public Vector3 flapVelocity;
public float maxSpeed = 5f;
bool didFlap = false;
// Use this for initialization
void Start () {
}
void update (){
if (Input.GetKeyDown (KeyCode.Mouse0))
{
didFlap = true;
}
}
// Update is called once per frame
void FixedUpdate () {
Velocity += gravity* Time.deltaTime;
if (didFlap) {
didFlap = false;
Velocity += flapVelocity;
}
Velocity = Vector3.ClampMagnitude (Velocity, maxSpeed);
transform.position += Velocity * Time.deltaTime;
}
}
can you please fix the error as every time i set the velocity in unity for the sprite ad run the program the sprite just keeps on falling and no matter how much i click or tap the space key the sprite does not stop falling even if i increase the velocity
First of all, the correct Update function is with a capital U, so Update() instead of update(). Then, since you're not doing anything with physics, you can do everything in Update and not use FixedUpdate at all. So you can remove the didFlap variable and add to Velocity directly inside the if (Input.GetKeyDown ...) block. Furthermore, regarding gravity, you're multiplying it twice with Time.deltaTimethere, so remove the first one. That should get you started.