I am a beginner Unity developer. I have created this.
The wizard on the top-right corner comes in from outside the screen when the game starts. Then stops and throws the axe. Which eventually hits the detective and causes him to fall.
The wizard and the axe have their scripts. There is no component attached to the wizard. The axe has a rigidbody (gravity scale set to 0) and a box collider attached.
Script of the wizard:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WizardMover : MonoBehaviour
{
public Vector3 move;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// Wizard stops at at a specific postion
if (transform.localPosition.x > 5.79)
{
transform.localPosition -= move;
}
}
}
And script for the axe:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AxeFly : MonoBehaviour
{
public Vector3 move;
public Vector3 rotate;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.localPosition -= move;
// Axe starts rotating when thrown
if (transform.localPosition.x < 5.80)
{
transform.Rotate(rotate);
}
}
}
Everything works as expected when I play this in Unity. But the speed of scripted movement and rotation of both the wizard and the axe gets significantly slow in the WebGL build. Why is this happening?
Your code is frame-rate dependent!
What this means is on a stronger device which can run with higher FPS (frames per second) your Update method is called more often within the same absolute real time as on a weak device with lower FPS.
So of course if you move with a fixed distance more often within the same time the object will in total travel further and vise versa.
For continous animations in Unity you should always use Time.deltaTime
The interval in seconds from the last frame to the current one (Read Only).
(or sometimes even Time.unscaledDeltaTime in cases where you want to ignore the current Time.timeScale)
which basically converts any value from value per frame into a value per second.
transform.localPosition -= move * Time.deltaTime;
and
transform.Rotate(rotate * Time.deltaTime);
adjust the move and rotate accordingly to the expected absolute value per second.
Related
I'm completely new (<1 week) to Unity, C# and game development generally. I'm starting out making a 2D isometric, grid-based CRPG and have hit a major wall with Unity's tilemaps.
I have a component which creates a tilemap tile underneath the parent GameObject using Tilemap.SetTile. As the GameObject moves around the grid, the tile should move with it and delete the previous tile. The tile can then create a moving obstacle node for pathfinding (which is working fine with static obstacles).
The problem is that the script actually does briefly work, just not for very long. If the GameObject moves along a path 'n' cells in a grid, the script will render 'n/2' cells every time the script is run, then stop working altogether. There's no error messages, freezing or anything, the tiles just aren't being drawn, and I know from logging in the console that the script is correctly tracking where the tiles should be drawn.
The obstacle script looks like this:
private void SetObstacleTile()
{
currentCell = obstacleMap.WorldToCell(transform.position);
if (currentCell != previousCell)
{
//set the new tile
obstacleMap.SetTile(currentCell, obstacleTile);
// erase previous
obstacleMap.SetTile(previousCell, null);
// save the new position for next frame
previousCell = currentCell;
Debug.Log(currentCell);
}
}
private void Update()
{
SetObstacleTile();
}
... and the movement currently looks like this:
void Update()
{
if (Vector3.Distance(transform.position, destination) > 0.01f)
transform.position = Vector3.MoveTowards(transform.position, destination, movementSpeed * Time.deltaTime);
}
My gut feeling is that it's something to do with how the Update() functions in the character movement and obstacle tiles component are interacting with each other but I don't have the experience to know how close I am to the problem. Any help with what could be causing this would be massively appreciated.
I am using the followng script to clamp the UI Image to the player in 2D game, but when the player is moving, the image is shaking a little. What am I doing wrong?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthBarClamp : MonoBehaviour
{
public Transform targetToFollow;
Transform thisTransform;
void Start()
{
thisTransform = transform;
}
void Update()
{
thisTransform.position = new Vector3(targetToFollow.position.x,
targetToFollow.position.y + 1.5f, thisTransform.position.z);
}
}
You can try to make the health bar children of your target in the gameObject hierarchy, so that it moves along with it with no need of updating its position in a script. You can then enable/disable the health bar upon your needs if you need it to be seen or not
If you're moving the target object around using physics or in FixedUpdate, then you'll need to move the camera around in FixedUpdate as well. Update happens every frame, fast or slow, whereas FixedUpdate is simulated to happen at consistent intervals to help keep physics calculations from going nuts. If you move the camera in Update and the target in FixedUpdate, then you'll end up with tiny differences that look like shaking.
(Or you can follow the advice given in the comments. It works perfectly fine to make a UI element a child of the moving object, although I personally prefer to do it the way you had it originally because it makes things like "smooth" camera movement easier.)
I tried to create a empty gameobject and put the first gameobject as child but it didn't fix the problem.
Just rotating the object a script is fine but if I'm using LookAt it's not rotating good since the gun is pointing on the red axis and the blue axis is on the body.
Wrong axis
I tried simple LookAt :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAT : MonoBehaviour
{
private GameObject target;
// Use this for initialization
void Start()
{
target = GameObject.FindGameObjectWithTag("Enemy");
}
// Update is called once per frame
void Update()
{
transform.LookAt(target.transform);
}
}
Then I tried this : This was a bit better it seems like it was facing with the red axis forward with the gun but not perfect still it didn't target perfect the target I think not sure and not sure if this is a good solution :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAT : MonoBehaviour
{
public float speed;
private GameObject target;
// Use this for initialization
void Start()
{
target = GameObject.FindGameObjectWithTag("Enemy");
}
// Update is called once per frame
void Update()
{
Vector3 direction = target.transform.position - transform.position;
Quaternion toRotation = Quaternion.FromToRotation(transform.right, direction);
transform.rotation = Quaternion.Lerp(transform.rotation, toRotation, speed * Time.time);
}
}
The second solution I tried seems the red axis with the gun is facing the target now but the gun and the rings on the base are stuttering and the rings rotating too but they should not rotate I think or they should not be part of the looking on the target.
In this screenshot the whole rings on the base are kind of looking at the target and make the whole turret looks strange. So I'm not sure how ot make this rings and other stuff rotating while only the turret turn object will face the target.
Wrong stuff is rotating and looking facing the target
Looks like the model has axis that don't line up with how you want to use it. Its reccomended that you fix the model, but alternatively you can also add a parent transform on top so you can add some rotation to your model.
Check this out for a more detailed explanation.
To get the two discrete axis of rotation thing I think you are describing at the end of your post you can add two parents as described in the post I linked and apply rotations to each of those parents individually.
I just started to use Unity and I found on Youtube a tutorial for my question(making an object move with arrow keys), but I have a problem. My object is constantly moving into the right bottom corner(x is going to minus and z is going to +, y is zero). I did the same thing as the guy in the tutorial.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.Translate(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, Input.GetAxis("Vertical") * Time.deltaTime);
}
}
Do you have a Rigidbody component added to your object?
If you do, uncheck "Use Gravity" and check "Is Kinematic" in the Unity Editor, inspector window.
That might help solve the problem.
I'm learning how to use Unity3D.
I have this scene where the elements are two PNG images (two black circles) to which I have associated the Rigidbody property (without gravity).
With a script I have associated the controller of the horizontal axis and it works: I can control the central circle with the keyboard.
Now I'm trying to associate a constant force. My script is as follows. But it only works along the Y axis. I can not make it work along the horizontal axis.
The script is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CircleController : MonoBehaviour {
float MaxSpeed = 10f;
Rigidbody rigid2D;
public Vector3 tensor;
// Use this for initialization
void Start()
{
rigid2D = GetComponent<Rigidbody>();
rigid2D.AddForce(new Vector3(0,10,0), ForceMode.Force);
}
// Update is called once per frame
void FixedUpdate()
{
float move = Input.GetAxis("Horizontal");
rigid2D.velocity = new Vector2(move * MaxSpeed, rigid2D.velocity.y);
}
}
Can someone help me to understand why I can not put a force along that axis?
In particular, when I execute the script with this instruction: rigid2D.AddForce(new Vector3(0,10,0), ForceMode.Force);, I see the central circle moving towards the other. This is right.
Instead, when I execute it with this instruction rigid2D.AddForce(new Vector3(10,0,0), ForceMode.Force); the central circle remains stationary.
You call the following line in the Start function (executed once)
rigid2D.AddForce(new Vector3(10,0,0), ForceMode.Force);
It applies a force to the rigidbody to the right by the given value (10). The Physics engine computes the acceleration to apply to the rigidbody and will automatically compute the velocity (speed) and new positions each frame.
However, in the FixedUpdate, you call the following lines
float move = Input.GetAxis("Horizontal");
rigid2D.velocity = new Vector2(move * MaxSpeed, rigid2D.velocity.y);
Here, you force the velocity of the rigidbody on the horizontal axis, overriding the value computed by the Physics engine. If you don't press the buttons defined in the Input manager, the circle will remain still on the horizontal axis since move is equal to 0.
When calling rigid2D.AddForce(new Vector3(0,10,0), ForceMode.Force);, the circle moves up, because rigid2D.velocity = new Vector2(move * MaxSpeed, rigid2D.velocity.y); keeps the velocity on the vertical axis.