So I made player and you can controll it with mouse/finger. You can move it to left/right and it's moving forward on it's own. But the problem is that it's too fast. Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour{
private SwerveInputSystem _swerveInputSystem;
[SerializeField] private float swerveSpeed = 5f;
[SerializeField] private float maxSwerveAmount = 1f;
[SerializeField] private float verticalSpeed;
void Start(){
_swerveInputSystem = GetComponent<SwerveInputSystem>();
}
void Update(){
float swerveAmount = Time.deltaTime * swerveSpeed * _swerveInputSystem.MoveFactorX;
swerveAmount = Mathf.Clamp(swerveAmount, -maxSwerveAmount, maxSwerveAmount);
transform.Translate(swerveAmount, 0, 0);
float verticalDelta = verticalSpeed * Time.deltaTime;
// Plug verticalDelta into Translate(). Whether you use it in the y or z component depends on your game.
transform.Translate(swerveAmount, verticalDelta, 1);
}
}
Whenever you want to directly translate something every frame you should make sure your values are not frame-based but rather time-based.
This means that no matter how fast or slow a device is you want your objects to move the same distance within the same actually passed time.
So just as with the values for the X and Y component you should also multiply the Z component by Time.deltaTime - the time passed since the last frame - in order to convert the value from a units / frame into units / second:
// will now move forward one Unity unit per second
transform.Translate(swerveAmount, verticalDelta, 1f * Time.deltaTime);
Just did this and it works:
transform.Translate(swerveAmount, verticalDelta, 0.1f);
Related
I'm working on a hand sway system. And the problem is that when I use Vector3.Lerp(); for it, it looks really bad and laggy :
https://streamable.com/64y52o
And this is my source code :
Transform target;
float smooth;
void Update()
{
transform.position = Vector3.Lerp(transform.position, target.transform.position, smooth * Time.deltaTime);
}
And this is my setup in editor :
enter image description here
The script is attached to Hand game object. And the target input is Hand Pos object in inspector.
I tried using both Vector3.Lerp(); and Vector3.Slerp(); but it didn't change anything.
I also tried running code on both Update() and FixedUpdate() and even LateUpdate() but not much changed.
Full code for source :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HandSway : MonoBehaviour
{
public float smooth;
public float swayMultiplier = 1f;
public Vector3 handOffset;
public Transform target;
private void Update()
{
float x = Input.GetAxisRaw("Mouse X") * swayMultiplier;
float y = Input.GetAxisRaw("Mouse Y") * swayMultiplier;
Quaternion xRot = Quaternion.AngleAxis(-y, Vector3.right);
Quaternion yRot = Quaternion.AngleAxis(x, Vector3.up);
Quaternion rotation = xRot * yRot * target.rotation;
transform.localRotation = Quaternion.Slerp(transform.localRotation, rotation, smooth * Time.deltaTime);
transform.position = Vector3.Lerp(transform.position, target.transform.position, smooth * Time.deltaTime);
}
}
There are a few different approaches when animating an object.
One is to start from position A and interpolate over T seconds to position B. This would be expressed in code like:
t += Time.deltaTime;
transform.position = Vector3.Lerp(A, B, t / T);
This should move the object with a constant speed. If you want to control the speed instead you you could compute T = A.Distance(B) / speed. If you want a constant acceleration instead you could use SLerp.
If you want the object to track the target continuously rather than animating it I would probably not recommend just using Lerp. This will result in a speed that is completely dependent on the distance. This would be equal to a proportional only regulation, see PID controller. Notably, if your proportional factor (i.e. smooth * Time.deltaTime) is larger than 1 you will get oscillations, that might be what is happening.
I would probably recommend that you instead calculate the direction to the target, and cap the speed. You might also want to cap the acceleration for a smoother animation.
I am trying to create a minigame similar to the fishing mechanism in Stardew Valley. I have two boundaries which are empty objects positioned at each end of a rectangle to keep the fish and the hook inside of the zone. When I run my script, the fish spawns at the bottom boundary and moves up instead of the position it is initially in. The hook generates at the bottom boundary and doesn't move upon user input.
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FishingMiniGame : MonoBehaviour
{
//Make the Egg move
[Header("Fishing Area")]
[SerializeField] Transform topBounds;
[SerializeField] Transform bottomBounds;
[Header("Fish Settings")]
[SerializeField] Transform Fish;
[SerializeField] float smoothMotion = 3f;
[SerializeField] float fishTimeRandomizer = 3f;
float fishPosition;
float fishSpeed;
float fishTimer;
float fishTargetPosition;
[Header("Hook Settinds")]
[SerializeField] Transform Hook;
[SerializeField] float HookSize = .18f;
[SerializeField] float HookSpeed = .1f;
[SerializeField] float HookGravity = .05f;
float hookPosition;
float hookPullVelocity;
private void FixedUpdate()
{
MoveFish();
MoveHook();
}
private void MoveHook()
{
if(Input.GetMouseButtonDown(0))
{
//increase our pull velocity
hookPullVelocity += HookSpeed * Time.deltaTime; //raises out hook
}
hookPullVelocity -= HookGravity * Time.deltaTime;
hookPosition += hookPullVelocity;
hookPosition = Mathf.Clamp(hookPosition, 0, 1); //keep the jook withon bounds
Hook.position = Vector3.Lerp(bottomBounds.position, topBounds.position, hookPosition);
}
private void MoveFish()
{
//based on timer, pick random position
//move fish to that position smoothly
fishTimer -= Time.deltaTime;
if(fishTimer < 0)
{
//pick a new target position
//reset timer
fishTimer = Random.value * fishTimeRandomizer;
fishTargetPosition = Random.value;
}
fishPosition = Mathf.SmoothDamp(fishPosition, fishTargetPosition, ref fishSpeed, smoothMotion);
Fish.position = Vector3.Lerp(bottomBounds, topBounds, fishPosition);
}
}
Well, first, making all the code in one script will be confuse. Try giving that fish its own script and game object.
Plus, take a look into Lerp. I think you are missundertanding how to use it. It takes 3 parameters with a being the original Vector3, so your current hook or fish position, b is your Vector3 target position, and t is the step or timestep. Should be delta or delta*someMultiplier.
What #MickyD said is also true, input should be performed during Update(), but that will not fix you code. Update(), FixedUpdate() and LateUpdate() are kinda the same but they run always in that order: Update -> FixedUpdate -> LateUpdate. So keep that in mind.
By the way, your gravity aplies every frame, so your hook is fighting against it even when you are lifting, resulting in half the force being neutralized. Making the gravity only apply on an else after your input will give you a much clear control of forces.
i try to create free look camera i was follow tutorial on YouTube everything work fine except i noticed that the rotation value about the y axis which is stored in float variable the angle value is getting Continue to accumulate i try to clamp it but its result in undesired behavior i also try the mathf.repeat the same i tried to zero the angle if it larger than 360 but this create another instant rotation in the opposite dir , i use the += operator which i think it causes this if I am not mistaken
my question dose this affect the performance i target mobile device's in general
If it affects performance, how should I deal with this problem?
thank you for any help really
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Camera : MonoBehaviour
{
public Transform target;
public float destotarget;
public float sensetivity;
public float smoothTime;
public float yaw;
public float pitch;
public Vector2 minandmax = new Vector2(34, 54);
public Vector3 currnetrot;
public Vector3 velocitysmooth;
// Update is called once per frame
void LateUpdate()
{
yaw += Input.GetAxis("Mouse X") * sensetivity;
pitch += Input.GetAxis("Mouse Y") * sensetivity;
pitch = Mathf.Clamp(pitch, minandmax.x, minandmax.y);
currnetrot = Vector3.SmoothDamp(currnetrot, new Vector2(pitch, yaw), ref velocitysmooth, smoothTime);
transform.eulerAngles = currnetrot;
transform.position = target.position - transform.forward * destotarget;
}
}
This shouldn't effect the performance much, but the only way to ever know is to profile:
https://docs.unity3d.com/Manual/profiler-profiling-applications.html
https://blog.theknightsofunity.com/mobile-optimization-unity-profiler/
I'm super new to coding and to this forum so forgive me if I break any taboo's here. I'm simply working on a 3rd person camera, just kind of messing around but I keep getting
UnassignedReferenceException: The variable CameraFollowObj of CameraFollow has not been assigned.
You probably need to assign the CameraFollowObj variable of the CameraFollow script in the inspector.
CameraFollow.CameraUpdater () (at Assets/Scripts/CameraFollow.cs:68)
CameraFollow.LateUpdate () (at Assets/Scripts/CameraFollow.cs:62)"
I've created an object for my camera to follow and placed it on the model. Then moved the object to what I believe to be the correct field but the issue still persists.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public float CameraMoveSpeed = 120.0f;
public GameObject CameraFollowObj;
Vector3 FollowPOS;
public float clampAngle = 80.0f;
public float InputSensitivity = 150.0f;
public GameObject CameraObj;
public GameObject PlayerObj;
public float camDistanecXToPlayer;
public float camDistanecYToPlayer;
public float camDistanecZToPlayer;
public float mouseX;
public float mouseY;
public float finalInputX;
public float finalInputZ;
public float smoothX;
public float smoothY;
private float rotY = 0.0f;
private float rotX = 0.0f;
// Start is called before the first frame update
void Start()
{
Vector3 rot = transform.localRotation.eulerAngles;
rotY = rot.y;
rotX = rot.x;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
// Update is called once per frame
void Update()
{
float InputX = Input.GetAxis("RightStickHorizontal");
float InputZ = Input.GetAxis("RightStickVertical");
mouseX = Input.GetAxis("Mouse X");
mouseY = Input.GetAxis("Mouse Y");
finalInputX = InputX + mouseX;
finalInputZ = InputZ + mouseY;
rotY += finalInputX * InputSensitivity * Time.deltaTime;
rotX += finalInputZ * InputSensitivity * Time.deltaTime;
rotX = Mathf.Clamp(rotX, -clampAngle, clampAngle);
Quaternion localRotation = Quaternion.Euler(rotX, rotY, 0.0f);
transform.rotation = localRotation;
}
void LateUpdate()
{
CameraUpdater();
}
void CameraUpdater()
{
Transform target = CameraFollowObj.transform;
float step = CameraMoveSpeed * Time.deltaTime;
transform.position = Vector3.MoveTowards (transform.position, target.position, step);
}
}
Make sure you haven't added the script to another gameobject somewhere else in the project that might cause this error.
You can search for the script in the scene search bar and all the gameObjects with the script attached will appear. Also in runtime if you right click on the script and in the contextual menu you select option kind of "find all the references in the scene" or something similar, you get all the instances of the script in your scene.
I think you should have drargged the script into another gameObject by mistake where the cameraToFollow gameObject is empty so you get the unnasigned error.
Hope this helps.
There are multiple things you can try to do:
Make sure you dragged the correct object in the field (I doubt that your character object is called CameraFollow)
Make sure that you dragged in an object from the Hierarchy and not the Assets window (ethats means that you need to drag in objects that are currently in the scene and can be seen on the hierarchy)
If you try everything from above and it doesen't work try assigning the object in the start function of the script. You can use GameObject.Find
Hope this helped to clarify a few things for you. Now if you really want to create a top level camera system you can also check this video out. Its an example of how to make a third person camera with the Cinemachine component (comes with Unity package manager for free)
I wish you luck with coding in Unity and welcome to the community :)
I'm playing around with projectile physics on objects in Unity. In this case I'm just using a sphere object and calculating it's vector and the path it should take based on gravity (leaving other forces like friction out for the moment).
The formula I'm using is the following: s = ut + ½at² and the code solution is simple enough as follows:
using UnityEngine;
using System.Collections;
public class TestProjectileForce : MonoBehaviour {
// Create vector components to calculate force & position
private float force = 1.8f;
private float g = 9.8f;
private float angle = 30f;
private float fx;
private float fy;
// projectile calculate
private float dis_x;
private float dis_y;
// Use this for initialization
void Start () {
// calculate x & y vector
fx = Mathf.Round (force * Mathf.Cos(Mathf.Deg2Rad * angle));
fy = Mathf.Round (force * Mathf.Sin(Mathf.Deg2Rad * angle));
}
// Update is called once per frame
void Update () {
// s = ut + 1/2at2
dis_x = (float)(fx * Time.timeSinceLevelLoad);
dis_y = (float)(fy + Time.smoothDeltaTime + (0.5) * (-g) * Time.timeSinceLevelLoad * Time.timeSinceLevelLoad);
Debug.Log (dis_x+", "+dis_y);
transform.Translate (new Vector2(dis_x, dis_y));
}
}
I noticed however, that the expected result i should get varies greatly depending on if i use Time.sinceLevelLoad over Time.deltaTime. Can anyone explain to me why this is? When using Time.sinceLevelLoad i get the expected result of the ball arcing and dropping given the force of gravity acting upon it, however with Time.deltatime the balls will just shoot off and not arc as expected.
Time.deltaTime is the time interval being processed by this Update. At 30fps it is 1/30s assuming no variance in frame rate. For physics you should use FixedUpdate which is always a fixed interval.
Time.timeSinceLevel load is at it says, the elapsed game time since loading the level.
They are very different concepts. The first can be used to derive an iterative solution, the second to evaluate a function over time (assuming you always want to evaluate from start of level load).