I have a character selection screen, when a certain button is pressed the assigned character will slide into view. Unfortunately for one of my character's they transform position seems to change putting them higher, etc making them not appear on the game screen. I'm not sure why as both character's have the same components and no where in code tells them to change position. The only script they have works as slide animation to make seem as though they glide into view instead of just appear. (attached below)
If I change the character's avatar int he animator to the same as the other character's then their position will be correct but then they will not do any animations.
Winter is the working GameObject.
Eunha is the one that changes position. Before the game starts Eunha's transform position is the same as Winter's shown in the Inspector.
private Vector3 startPosition;
private void Awake()
{
finalPosition = transform.position;
startPosition = finalPosition - transform.right * 5.0f;
}
private void Update()
{
transform.position = Vector3.Lerp(transform.position, finalPosition, 0.1f);
}
private void OnEnable()
{
transform.position = startPosition;
} ```
The codeing order seems to be problem. I recommend using 2 empty objects to determine location. This script is more efficient and reliable.
public Transform startPosition; // place on start position
public Transform endPosition; // place on shifted position
public float duration = 1f;
public void OnEnable() => StartCoroutine(Shift());
public IEnumerator Shift()
{
var shiftProgress = 0f;
while (shiftProgress < 1)
{
shiftProgress += Time.deltaTime/duration;
transform.position = Vector3.Lerp(startPosition.position, endPosition.position, shiftProgress);
yield return new WaitForEndOfFrame();
}
}
Related
So I'm new to Csharp, and I am working on this script for a game. It's a 2D game. Ive already assigned jump movement to the game, however, I'm stuck on fixing the movement along the x axis.
I'd really appreciate your help.
using UnityEngine;
// this code uses physics to make player jump
public class Movement2d : MonoBehaviour
{
private bool jumpKeyWasPressed;
private bool movementRight;
private CharacterController characterController;
private Rigidbody2D rigidbodyComponent;
private Vector3 moveSpeed;
// Start is called before the first frame update
void Start()
{
rigidbodyComponent = GetComponent<Rigidbody2D>();
characterController = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
//Check if space key is pressed down
if (Input.GetKeyDown(KeyCode.Space))
{
jumpKeyWasPressed = true;
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
movementRight = true;
}
}
private void FixedUpdate()
{
if (jumpKeyWasPressed)
{
//jump action assigned to space key
rigidbodyComponent.AddForce(new Vector2(0, 10), ForceMode2D.Impulse);
jumpKeyWasPressed = false;
}
if (movementRight)
{
//moving right assigned to right arrow
Rigidbody.MovePosition();
}
}
}
If you're using RigidBody.MovePosition, you'll want to move the player according to your speed and the time elapsed since the last frame (to account for frame stutters).
Assuming your horizontal speed is stored in the x-coordinate of your speed vector, you'll want to write:
rigidBodyComponent.MovePosition(new Vector2(moveSpeed.x * Time.deltaTime, 0));
To perform left movement, use the same code, but use -moveSpeed.x instead. In both cases, don't forget to set the movement bool to false afterwards.
Keep in mind, however, that using RigidBody.MovePosition could cause your character to go through walls at high speeds. Consider using RigidBody.AddForce() as you did for jumping if you want to avoid that.
Sources:
https://docs.unity3d.com/ScriptReference/Rigidbody2D.MovePosition.html
https://docs.unity3d.com/ScriptReference/Rigidbody2D.AddForce.html
I am trying to make a game in Unity that when the player (with oculus quest controller) grab the object he can rotate it without moving the object ,on a fixed position. I am having problem with transforming the local position of the controllers to the locale position of the object and rotate it with c#. please help me I am still new in this.
**edit: here is the last I tried:
[Header("Controller")]
public OVRInput.Button grabButton;
public GameObject target;
public float speed=0.01f;
//Quaternion m_MyQuaternion;
public Vector3 targetPosition;
void Update()
{
if (OVRInput.Get(grabButton))
{
targetPosition = new Vector3(taregt_eulerAngX, taregt_eulerAngY, target_eulerAngZ);
if (Vector3.Distance(transform.eulerAngles, targetPosition) > 0.01f)
{
transform.eulerAngles = Vector3.Lerp(transform.rotation.eulerAngles, targetPosition, Time.time * speed);
}
}
}
the target in this case is the left hand, so when I grab the gameobj it will rotate accordingly to the hand(controller)
I'm pretty new to Unity. I tried to create a script that the camera would follow the actor (with a little difference). Is there a way to improve the code? It works just fine. But I wonder if I did it the best way. I want to do it about as I wrote, so if you have any tips. Thank you
Maybe change Update to FixedUpdate ?
public GameObject player;
// Start is called before the first frame update
void Start()
{
player = GameObject.Find("Cube"); // The player
}
// Update is called once per frame
void Update()
{
transform.position = new Vector3(player.transform.position.x, player.transform.position.y + 5, player.transform.position.z - 10);
}
Making the camera following the player is quite straight forward.
Add this script to your main camera.
Drag the reference of the player object to the script and then you are done.
You can change the values in the Vector 3 depending on how far you want the camera to be from the player.
using UnityEngine;
public class Follow_player : MonoBehaviour {
public Transform player;
// Update is called once per frame
void Update () {
transform.position = player.transform.position + new Vector3(0, 1, -5);
}
}
Follows player in the back constantly when the player rotates, no parenting needed, with smoothing.
Piece of Knowledges:
Apparently, Quaternion * Vector3 is going to rotate the point of the Vector3 around the origin of the Vector3 by the angle of the Quaternion
The Lerp method in Vector3 and Quaternion stand for linear interpolation, where the first parameter gets closer to the second parameter by the amount of third parameter each frame.
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public Transform target;
public float smoothSpeed = 0.125f;
public Vector3 locationOffset;
public Vector3 rotationOffset;
void FixedUpdate()
{
Vector3 desiredPosition = target.position + target.rotation * locationOffset;
Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
transform.position = smoothedPosition;
Quaternion desiredrotation = target.rotation * Quaternion.Euler(rotationOffset);
Quaternion smoothedrotation = Quaternion.Lerp(transform.rotation, desiredrotation, smoothSpeed);
transform.rotation = smoothedrotation;
}
}
This will always follow the player from the same direction, and if the player rotates it will still stay the same. This may be good for top-down or side-scrolling view, but the camera setup seems to be more fitting for 3rd person, in which case you'd want to rotate the camera when the player turns.
The easiest way to do this is actually not with code alone, simply make the camera a child of the player object, that way its position relative to the player will always stay the same!
If you do want to do it through code, you can change the code to be like this:
void Update()
{
Vector3 back = -player.transform.forward;
back.y = 0.5f; // this determines how high. Increase for higher view angle.
transform.position = player.transform.position - back * distance;
transform.forward = player.transform.position - transform.position;
}
You get the direction of the back of the player (opposite of transform's forward). Then you increase the height a little so the angle will be a bit from above like in your example. Last you set the camera's position to be the player's position and add the back direction multiplied by the distance. That will place the camera behind the player.
You also need to rotate the camera so it points at the player, and that's the last line - setting the camera's forward direction to point at the player.
Here is just another option. I always find it easier to have the variables which are populated in the inspector so you can adjust it and fine tune it as needed.
public GameObject player;
[SerializeField]
private float xAxis, yAxis, zAxis;
private void Update()
{
transform.position = new Vector3(player.transform.position.x + xAxis, player.transform.position.y + yAxis, player.transform.position.z + zAxis);
}
I got a small arena where the player can move on. At the sides of the area there are spawners. These spawners instantiate bombs and should throw them at the player.
For the direction I actually use
transform.lookAt(playerTransform);
So this is a rough map
So the spawners are rotating around the map. They move from one point to the next point.
My bomb object got a rigidbody attached and the gravity is activated. I just need to find out how to make a spawner throwing a bomb to the player.
public class BombSpawner : MonoBehaviour
{
[Range(0, 3)]
[SerializeField]
private int nextPointIndex; // set the first targetpoint
private Vector3[] targetPoints = {
new Vector3(-15,0,15),
new Vector3(15,0,15),
new Vector3(15,0,-15),
new Vector3(-15,0,-15)};
private float movementSpeed = 10;
GameObject bombPrefab;
Transform player;
private void Start()
{
bombPrefab = Resources.Load(StringCollection.BOMB) as GameObject;
player = Globals.GetPlayerObject().transform;
}
private void Update()
{
transform.LookAt(player); // set the object rotation
Vector3 nextPoint = targetPoints[nextPointIndex]; // get the target point
transform.position = Vector3.MoveTowards(transform.position, nextPoint, movementSpeed * Time.deltaTime); // move the spawner
if (transform.position == nextPoint) // point reached? set a new point
{
if (nextPointIndex < targetPoints.Length - 1)
nextPointIndex++;
else
nextPointIndex = 0;
}
}
}
So I could write a method like this
void SpawnBomb()
{
GameObject spawnedBomb = Instantiate(bombPrefab);
}
but how do I achieve the throwing mechanic? For a first try, the targetPoint is player.position that should be fine.
You need to get the direction from spawner to the current position of the target, spawn the bomb and add force to that bomb using the direction you just got.
In order to do this you should substract your spawner's position from your target position.
Vector3 dir = target.transform.position - transform.position;
Now that you have the direction you can spawn your bomb and AddForce() to it. To add force you need to call the Rigidbody component of your spawned Bomb, like this:
spawnedBomb.GetComponent<Rigidbody>().AddForce(dir.normalized * force, ForceMode.Impulse);
Where dir is the direction towards the target (normalized - so the distance doesn't matter) and force is pretty much the speed of the bomb.
Here you can read more about Rigidbody.AddForce.
I am trying to create a drag and drop functionality. I have a game object that lies on a cube (like a table). I want to allow the player to drag and drop this object to multiple "hot spots". At the same time, while this is a 3D game, they should not be allowed to drag the object off of the table, above it, bellow it, etc. Just drag across the top of the table. The way I have this setup is like this:
On the table top (a cube with a rigid body)I have two planes. This plane is just decorative to let the user see where to drop to. Each of these planes has a child plane (a much smaller area, centered in the parent). This child has a Box Collider (isTrigger= true) that extends high up into the air, like a pole sticking out of the ground)
I then have a cube that has a rigid body and a box collider (isTrigger= true). This cube is instantiated onto the "table" top, over one of the hot spots.
HotSpotCode.cs
public class HotSpotCodeScript : MonoBehaviour {
public void OnTriggerEnter(Collider other){
DraggableObject ds = other.GetComponent<DraggableObject>();
ds.startPos = this.gameObject.transform.position;
}
}
DraggableObject.cs
public class DraggableObject : MonoBehaviour {
float lerpTime = 1f;
float currentLerpTime;
float moveDistance = 10f;
Plane plane;
public Vector3 startPos, endPos;
public bool drag;
Vector3 position;
void Start(){
startPos = transform.position;
endPos = transform.position + transform.up * moveDistance;
}
void OnMouseDown(){
plane = new Plane(Vector2.up, transform.position);
drag = true; // start dragging
}
void OnMouseUp(){
lerp();
drag = false;
}
private void lerp() {
currentLerpTime += Time.deltaTime;
if (currentLerpTime > lerpTime)
{
currentLerpTime = lerpTime;
}
float perc = currentLerpTime / lerpTime;
transform.position = Vector3.Lerp(startPos, endPos, perc);
}
public void Update()
{
position = transform.localPosition;
if (drag)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float distance;
if (plane.Raycast(ray, out distance))
{
transform.position = ray.GetPoint(distance);
}
}
}
public void OnTriggerEnter(Collider other){
endPos = other.transform.position;
}
}
This code mostly works somewhat. I am able to drag the object around and it won't leave the plan it it resides on, for short distances. But, the further away I drag the object, then release it, the more likely it is that the object will not snap back to its original start position and will get stuck somewhere along the way. I am not sure if this is an issue with the Lerp() function or maybe how the plane it is dragged across is created. Can anyone help me out? If you need more info, please let me know. I've been working on this for weeks and haven't gotten much further that this.
Another issue that pops up, as well, is that when the object that is being dragged is released, and comes into contact with the hot spot's collider, it stops the object at its exact point. So, if a corner of the cube comes into contact with the collider, the cube will not come to rest centered on the hot spot.