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!
Related
I have a weird problem and cant seem to fix it. I was creating my first game in Unity and I was testing around a bit after creating a movement system and whenever I touch another object (it doesn't matter if it has a rigid body or not), my player suddenly starts moving on its own. I have a video showing what exactly happens: https://youtu.be/WGrJ0KNYSr4
I have tried a few different things already and I determined that it has to do something with the physics engine because it only happens when the player isn't kinematic. So, I tried to increase the solver iterations for physics in the project settings, but the bug was still happening. I looked for answers on the internet, yet the only thing I found was to remove Time.deltaTime, though it still doesn't work. I have found that it seems to happen less though when the player is moving fast.
I would really appreciate if somebody could help me with this. This is my first real game and I'm creating it for the Seajam that's happening on itch.io.
Here is the code for my playercontroller script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float playerSpeed = 3f;
private Rigidbody playerRb;
public GameObject cameraRotation;
// Start is called before the first frame update
void Start()
{
playerRb = GetComponent<Rigidbody>();
}
float verticalSpeed;
float horizontalSpeed;
bool isOnGround = true;
// Update is called once per frame
void Update()
{
//get controlled forward and backward motion
verticalSpeed = Input.GetAxis("Vertical");
transform.Translate(Vector3.forward * playerSpeed * verticalSpeed * Time.deltaTime);
//get controlled sidewards motion
horizontalSpeed = Input.GetAxis("Horizontal");
transform.Translate(Vector3.right * playerSpeed * horizontalSpeed * Time.deltaTime);
//lock the rotation of the player on the z and x axis
transform.eulerAngles = new Vector3(0, cameraRotation.transform.eulerAngles.y, 0);
//when pressing space jump and prevent air jump
if (Input.GetKeyDown(KeyCode.Space) && isOnGround)
{
playerRb.AddForce(Vector3.up * 10, ForceMode.Impulse);
isOnGround = false;
}
}
//check if the player is on the ground
private void OnCollisionEnter(Collision collision)
{
isOnGround = true;
}
}
Try not locking the player's rotation by script, maybe it is causing the problem due to gimbal lock. Instead go to your player's RigidBody->Constraints and then lock it.
You can read more about it here https://fr.wikipedia.org/wiki/Blocage_de_cardan
Okay so I've been fighting with this script for a couple days now. I've made progress in other aspects but I can't seem to get my enemies to properly chase the player character.
The script is supposed to have the enemies wander until an empty child 'eyes' sees the player. Then it should start chasing the player. Think pac-man. What it's doing right now is making one loop of it's wander cycle and then stopping and not seeing the player at all.
This is the code that I've got so far for that script -
using UnityEngine;
using System.Collections;
public class dudeFollow : MonoBehaviour {
Transform tr_Player;
float f_MoveSpeed = 3.0f;
private DudeMove moveScript;
public Transform eyes;
public float sightRange = 3f;
// Use this for initialization
void Start () {
tr_Player = GameObject.FindGameObjectWithTag("Player").transform;
moveScript = GetComponent<DudeMove>();
}
// Update is called once per frame
void Update () {
RaycastHit hit;
if (Physics.Raycast (eyes.transform.position,eyes.transform.forward, out hit,sightRange) && hit.collider.CompareTag ("Player")) {
transform.position += transform.forward * f_MoveSpeed * Time.deltaTime;
moveScript.enabled = false;
}
}
}
Any help or tips would be appreciated.
Because you have 2D game, what most likely happens is your enemy wonders away on z-axis as well, but because it's 2D, you can't see it. So switch to 3D mode in your main scene window and see if that's the case.
If it is, just reset z-axis to 0 on every frame and disable angular momentum :) I had this happen with 2D games.
void Update () {
RaycastHit hit;
if (Physics.Raycast (eyes.transform.position,eyes.transform.forward, out hit,sightRange) && hit.collider.CompareTag ("Player")) {
transform.position += transform.forward * f_MoveSpeed * Time.deltaTime;
moveScript.enabled = false;
}
transform.position.z = 0; // or something along those lines, I don't remember the syntax exactly.
}
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.
I'm writing a 2D game and I'm trying to get moving platforms to work. After doing some previous investigation, I have it ALMOST working. The idea is to have 2 platform objects with colliders: 1 a visible object, the other an invisible object with isTrigger set (since the player would just go through a trigger). The code for the Moving Platform child (the trigger one) is set here.
using UnityEngine;
using System.Collections;
public class MovingPlatformChild : MonoBehaviour
{
public string parentPlatform = "";
void Start ()
{
transform.parent = GameObject.Find(parentPlatform).transform;
}
// Update is called once per frame
void Update ()
{
}
void OnTriggerEnter(Collider playerObject)
{
Debug.Log ("enter moving platform");
if(playerObject.gameObject.name.Contains("Player"))
{
playerObject.transform.parent = gameObject.transform;
}
}
int i = 0;
void OnTriggerStay(Collider playerObject)
{
Debug.Log ("stay" + i++);
if(playerObject.transform.position.y >= transform.position.y)
{
playerObject.transform.parent = gameObject.transform;
}
else
{
playerObject.transform.parent=null;
}
}
void OnTriggerExit(Collider playerObject)
{
Debug.Log ("EXIT");
if(playerObject.gameObject.name.Contains("Player"))
{
playerObject.transform.parent=null;
}
}
}
The Start() function just makes it a child of the visible platform. This can probably be done right in the Unity editor as well, instead of through code.
The OnTriggerEnter function adds the player object as a child of the trigger platform object, which is a child of the visible platform. So they should all move together.
The OnTriggerStay is an attempt to verify that this remains true only while the player is on the top of the platform. While the player is within the trigger, if the player is on top of the platform, then it remains attached. Otherwise, it's not. This is so that nothing happens on the bottom end.
The OnTriggerExit function just removes the player object as a child when it exits the trigger.
This is somewhat working (but we know somewhat isn't good enough). It works sometimes, but the player will be very jittery. Also, on the way down while standing atop the platform, the TriggerStay function doesn't appear to be called (implying the player is no longer within the trigger). This is observed through my Debug "stay" statement. Finally, sometimes the player will also fall straight through the platform.
What in this code would allow the player to fall through the platform, or be so jittery on the way up? Am I missing something crucial? If you need any more code, please let me know.
Below is the code for the movement of the non-trigger platform (the parent of the trigger platform and in an identical position). I will also share the Player's Update function after that.
void Start ()
{
origY = transform.position.y;
useSpeed = -directionSpeed;
}
// Update is called once per frame
void Update ()
{
if(origY - transform.position.y > distance)
{
useSpeed = directionSpeed; //flip direction
}
else if(origY - transform.position.y < -distance)
{
useSpeed = -directionSpeed; //flip direction
}
transform.Translate(0,useSpeed*Time.deltaTime,0);
}
And now the player code:
void Update()
{
CharacterController controller = GetComponent<CharacterController>();
float rotation = Input.GetAxis("Horizontal");
if(controller.isGrounded)
{
moveDirection.Set(rotation, 0, 0); //moveDirection = new Vector3(rotation, 0, 0);
moveDirection = transform.TransformDirection(moveDirection);
//running code
if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) //check if shift is held
{ running = true; }
else
{ running = false; }
moveDirection *= running ? runningSpeed : walkingSpeed; //set speed
//jump code
if(Input.GetButtonDown("Jump"))
{
//moveDirection.y = jumpHeight;
jump ();
}
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
EDIT: I've added the specifications for the platforms and player in this imgur album:
http://imgur.com/a/IxgyS
This largely depends on the height of your trigger box, but it's worth looking into. Within your TriggerStay, you've got an IF statement concerning the player y coordinates. If the trigger box is fairly large and the platform's speed fast enough, on the way up and between update ticks the player Y coords could momentarily be smaller than the trigger Y coords. This would lead to him losing the parentage, only to regain it a few ticks later. This might be the cause of the 'jittering'.
The problem I was having included
The moving platform was written using Translate. I rewrote it using a rigidbody and the rigidbody.Move function. This didn't immediately help, but...
I realized the CharacterMotor script (Unity provides this) that I had attached to the player included moving platform support. I set the MovementTransfer value to PermaLocked, and also unchecked the "Use FixedUpdate" box on the script, and it now works 99% of the time. I've had one time where I did a particular behaviour and slipped through, but I can't recreate it.
Hope this helps anyone who might be looking for an answer!