I'm trying to make a simple VR movement script using teleportation. I used three empty GameObjects to generate with them Quadratic BezzierCurve. p0 is a GameObject inside the player; it's moving with the player. My problem is that points (Gameobjects) aren't relative to player. When p0 is in position 0, 0, 0, the script works fine; but when I hooked it up to player and I move the player around scene, these points are not relative to player. I think I messed up with some basic stuff.
using UnityEngine;
public class settingPos : MonoBehaviour
{
public Transform tf;
public GameObject p0, p1, p2;
// 3 empty GameObjects to paste them into QuadraticBezzier Script which uses it for
// generate bezzier curve. p0 is gameObject inside player, it is moving with player
public float UpForce; //simply value for scaling Bezzier curve
Vector3 [] dir= new Vector3[2];
void Update ()
{
dir[0] = p0.transform.position;
Vector3 temp = transform.rotation * Vector3.forward;
temp *= UpForce;
dir[0] += temp;
dir[1] = new Vector3(dir[0].x * 2, 0, dir[0].z * 2); // This is end point of bezzier
// curve. I mentioned that
// distance between end-point
// and height of bezzier curve
// was this same as start-point
// and height.
p1.transform.position = dir[0];
p2.transform.position = dir[1];
}
}
Pretty short
It should look this same, but in other position.
This shows my issue
Related
I'm doing a simple game to get started with unity, there's a cube who goes straight and dodge other cubes (obstacles) which are spawned randomly. To make the obstacle always spawn in front of the player I set up a code that makes the 7 spawn position (the blocks get generated in them randomly) follow the player's coordinates but adding 100 to the Z so they get generated not upside the player. Now, my problem is that when generated the obstacle also changes their X position, making them fall from the platform when I go to the right or to the left with the player. How can I make they follow only the Z position of the player and not the X?
Here is the code that makes the spawners change position:
public class MoveSpawn : MonoBehaviour
{
public Transform player;
public Vector3 offset;
// Update is called once per frame
void Update()
{
transform.position = player.position + offset;
}
}
I would simply multiply the player's position by (0,0,1) (in other words, Vector3.forward) before adding it to the offset:
public class MoveSpawn : MonoBehaviour
{
public Transform player;
public Vector3 offset;
// Update is called once per frame
void Update()
{
transform.position = player.position * Vector3.forward + offset;
}
}
Oh, that's pretty easy.
So if you only want to look at the Z(or any other) coordinates of the Cube or any object in Unity you can simply use:
transform.position.z
That's the same thing you would do with vectors. Something like that:
Vector3 offset = ...;
Debug.Log(offset.x) //returns x coordinate of offset
Currently I am trying to write a script that will mirror the movements of one controller onto the other for users who only have 1 functioning arm. How do I mirror the position of the one controller onto the other that way the arms are in bilateral movement?
Mirroring the y axis and z axis were easy since they move together and the rotation was easy to mirror. I am unable to mirror the x axis movement. I want it so that if the one hand moves out the other does the same, and they both move in together. Any ideas how I may be able to do this? I have attached my current script. I also disabled the position tracking of the non mirrored controller with simple Boolean logic in the OVRCemeraRig script to prevent stutters in movement Need to use OVRCemeraRig since using final IK
I have tried taking a difference in the x positions in the working arm and then adding that value to the none working arm. That did not work.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VRMirror : MonoBehaviour
{
public bool mirrorLeft;
public bool mirrorRight;
public GameObject leftHand; //left hand anchor in OVRCameraRig
public GameObject rightHand; //right hand anchor from OVRCameraRig
void Start()
{
}
void FixedUpdate()
{
Transform left = leftHand.GetComponent<Transform>();
Transform right = rightHand.GetComponent<Transform>();
if (mirrorLeft)
{
Vector3 leftPos = left.position;
Quaternion leftRot = left.rotation;
leftRot.y = -leftRot.y;
right.position = leftPos;
right.rotation = leftRot;
}
else if (mirrorRight)
{
Vector3 rightPos = right.position;
Quaternion rightRot = right.rotation;
rightRot.y = -rightRot.y;
left.position = rightPos;
left.rotation = rightRot;
}
}
}
For the sake of robustness, let's assume your player's body's rotation might not necessarily always have its right pointing in the (1,0,0) world direction. Instead, we can get a reference to the player's Transform, playerTransform, (be sure to assign it using the inspector or in Start if you must) and make our calculations using that.
To calculate the bilateral symmetric position for a relative vector, you can calculate relativeVec - 2f * playerTransform.right * Vector3.Dot(relativeVec, playerTransform.right);. Explanation for why that works is in the comments.
For position, we can convert the absolute position of the source hand to be relative to the player's position, then find the relative position of the destination hand, then convert that back into an absolute position.
For rotation, determine up & forward for the source hand and reflect them to determine the up & forward for the destination hand. Use Quaternion.SetLookRotation to convert the vectors to the rotation for the destination hand.
We can use the same code for relative positions and for our direction vectors, so it actually doesn't take much code once you have the math. And also, since Transform is a class, we can make one method that does the reflection procedure, and then pass into it which transforms we want to be the source and destination:
public class VRMirror : MonoBehaviour
{
public bool mirrorLeft;
public bool mirrorRight;
public GameObject leftHand; //left hand anchor in OVRCameraRig
public GameObject rightHand; //right hand anchor from OVRCameraRig
public Transform playerTransform;
void Start()
{
}
void FixedUpdate()
{
Transform left = leftHand.GetComponent<Transform>();
Transform right = rightHand.GetComponent<Transform>();
if (mirrorLeft)
{
MirrorFromTo(left, right);
}
else if (mirrorRight)
{
MirrorFromTo(right, left);
}
}
void MirrorFromTo(Transform sourceTransform, Transform destTransform)
{
// Determine dest position
Vector3 playerToSourceHand = sourceTransform.position - playerTransform.position;
Vector3 playerToDestHand = ReflectRelativeVector(playerToSourceHand);
destTransform.position = playerTransform.position + playerToDestHand ;
// Determine dest rotation
Vector3 forwardVec = ReflectRelativeVector(sourceTransform.forward);
Vector3 upVec = ReflectRelativeVector(sourceTransform.up);
destTransform.rotation = Quaternion.LookRotation(forwardVec,upVec);
}
Vector3 ReflectRelativeVector(Vector3 relativeVec)
{
// relativeVec
// Take the relative vector....
// + Vector3.Dot(relativeVec, playerTransform.right)
// and for how far along the player's right direction it is
// away from the player (may be negative),
// * playerTransform.right
// move it that distance along the player's right...
// * -2f
// negative two times (i.e., along the left direction 2x)
return relativeVec
+ Vector3.Dot(relativeVec, playerTransform.right)
* playerTransform.right
* -2f;
}
}
I made some alteration to what #Ruzihm had. Thank you so much for the help. Everything works perfectly in the code I sampled below but I would recommend #Ruzihm answer since how he handles rotations. This code works if the player model is stationary and you are not turning your full body. If you need to turn use: playerTransform.right instead of Vector3.right in the ReflectRelativeVector function but using playerTransform.right will move the arm as the head moves.
public class VRMirror : MonoBehaviour
{
public bool mirrorLeft;
public bool mirrorRight;
public GameObject leftHand; //left hand anchor in OVRCameraRig
public GameObject rightHand; //right hand anchor from OVRCameraRig
public Transform playerTransform;
void Start()
{
}
void FixedUpdate()
{
Transform left = leftHand.GetComponent<Transform>();
Transform right = rightHand.GetComponent<Transform>();
if (mirrorLeft)
{
MirrorFromTo(left, right);
}
else if (mirrorRight)
{
MirrorFromTo(right, left);
}
}
void MirrorFromTo(Transform sourceTransform, Transform destTransform)
{
// Determine dest position
Vector3 playerToSourceHand = sourceTransform.position - playerTransform.position;
Vector3 playerToDestHand = ReflectRelativeVector(playerToSourceHand);
destTransform.position = playerTransform.position + playerToDestHand;
// Determine dest rotation
Quaternion destRot = sourceTransform.rotation;
destRot.y = -destRot.y;
destRot.z = -destRot.z;
destTransform.rotation = destRot;
}
Vector3 ReflectRelativeVector(Vector3 relativeVec)
{
// relativeVec
// Take the relative vector....
// + Vector3.Dot(relativeVec, playerTransform.right)
// and for how far along the player's right direction it is
// away from the player (may be negative),
// * playerTransform.right
// move it that distance along the player's right...
// * -2f
// negative two times (i.e., along the left direction 2x)
return relativeVec
+ Vector3.Dot(relativeVec, Vector3.right)
* Vector3.right
* -2f;
}
}
Here is a screen shot of the editor:
NavmeshAgent player not parallel to slope of hill when moving over hill. On plane surface its going smoothly.
See Video
Below Image properties of navMesh and player
https://ibb.co/fijmoV
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class SampleAgentScript : MonoBehaviour {
public Transform target ;
NavMeshAgent agent;
// private static bool start1=false , start2=false, start3;
// Use this for initialization
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
//if white button click moves to targer-1
agent.SetDestination(target.position);
}
}
I am not sure if NavmeshAgent is supposed to do that for you. This looks like something you're supposed to do manually.
You can correct the rotation of the character to match the slope by performing a raycast downwards and obtaining the normal of the hit point. After obtaining the normal of the hit point, you can then calculate the new rotation with that normal hit point. There are many ways to do that calculation but using Quaternion.FromToRotation and lerping the rotation with Quaternion.Lerp seems to work best.
Finally, make sure to the raycast is only done to Objects you considered as a "Hill" or "Ground". You can do this with the bitwise operation on the layer the "Hill" or "Ground" objects are placed on. The example below assumes that the Objects you consider as "Hill" or "Ground" are on a layer called "Hill".
//Reference of the moving GameObject that will be corrected
public GameObject movingObject;
//Offset postion from where the raycast is cast from
public Vector3 originOffset;
public float maxRayDist = 100f;
//The speed to apply the corrected slope angle
public float slopeRotChangeSpeed = 10f;
void Update()
{
//Get the object's position
Transform objTrans = movingObject.transform;
Vector3 origin = objTrans.position;
//Only register raycast consided as Hill(Can be any layer name)
int hillLayerIndex = LayerMask.NameToLayer("Hill");
//Calculate layermask to Raycast to.
int layerMask = (1 << hillLayerIndex);
RaycastHit slopeHit;
//Perform raycast from the object's position downwards
if (Physics.Raycast(origin + originOffset, Vector3.down, out slopeHit, maxRayDist, layerMask))
{
//Drawline to show the hit point
Debug.DrawLine(origin + originOffset, slopeHit.point, Color.red);
//Get slope angle from the raycast hit normal then calcuate new pos of the object
Quaternion newRot = Quaternion.FromToRotation(objTrans.up, slopeHit.normal)
* objTrans.rotation;
//Apply the rotation
objTrans.rotation = Quaternion.Lerp(objTrans.rotation, newRot,
Time.deltaTime * slopeRotChangeSpeed);
}
}
Needed help here, I've been following this tutorial about Enemy Patrolling, https://www.youtube.com/watch?v=KKU3ejp0Alg
The tutorial tell us to set 2 Empty Game Objects and the coordinates so the sprite will walk from one direction to another, the walking does working, however the rotation of the sprite became really weird, the 'Worm' sprite is suppose to move left and right now it change into facing upward
Please look at this image,
When moving from left to right
When moving from right to left
public Transform[] patrolPoints;
public float speed;
Transform currentPatrolPoint;
int currentPatrolIndex;
// Use this for initialization
void Start()
{
currentPatrolIndex = 0;
currentPatrolPoint = patrolPoints[currentPatrolIndex];
}
// Update is called once per frame
void Update()
{
transform.Translate(Vector3.up * Time.deltaTime * speed);
if (Vector3.Distance(transform.position, currentPatrolPoint.position) < .1f) {
if (currentPatrolIndex + 1 < patrolPoints.Length)
currentPatrolIndex++;
else
currentPatrolIndex = 0;
currentPatrolPoint = patrolPoints[currentPatrolIndex];
}
Vector3 patrolPointDir = currentPatrolPoint.position - transform.position;
float angle = Mathf.Atan2(patrolPointDir.y, patrolPointDir.x) * Mathf.Rad2Deg - 90f;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.RotateTowards(transform.rotation, q, 180f);
}
This is the code
Thank you
You can pass the optional parameter Space.World to your translation to move your object relative to world space instead of object space. That should prevent your object from rotating.
transform.Translate(Vector3.up * Time.deltaTime * speed, Space.World);
You can read more about it in the documentation.
You probably rotated the enemy sprite by 90 degrees. Try placing all your scripts into empty game object with no rotation, than place the enemy sprite as child of the empty game object and rotate as you need. This way your logic won't collide with your graphics.
I have a character in a 2D game, my goal is to get his eyes look as if they are looking at the cursor by moving the circles used for pupils towards the cursor, with limits. I have been stuck trying to create this for two days now and have yet to find a way that works!!
Using the following code I was able move my eyes towards the cursor, however this only works around the bottom left of the screen! (If the cursor is not below the screen or to the left of the screen the eyes move to the top right)
using UnityEngine;
using System.Collections;
public class LookAtMouse : MonoBehaviour {
public float speed = 5f;
private Vector3 target;
public Transform origin;
void Start () {
target = transform.position;
}
void Update () {
target = (Input.mousePosition);
target.z = transform.position.z;
transform.position = Vector3.MoveTowards(origin.position, target, speed * Time.deltaTime);
}
}
If anyone could point me in the right direction I would be incredibly grateful!
Thank you :)
Likely the reason it's only working in one quadrant for you is because Input.mousePosition returns a position in pixel coordinates. Basically, if your window is 800x600 pixels, it will return...
(0, 0, 0) for the bottom left pixel of the screen
(0, 600, 0) for the top left pixel of the screen
(800, 0, 0) for the bottom right pixel of the screen
(800, 600, 0) for the top right pixel of the screen
Since your eye pupil is in world space, you want the mouse position in world space also. Either way, even if you fixed that, I don't think Vector3.MoveTowards is going to do quite what you're wanting to do. I think this is more along the lines of what you want:
using UnityEngine;
public class LookAtMouse : MonoBehaviour {
public float speed = 5f;
public float maxDistance = 1f;
public Camera mainCamera;
private Vector3 _origin;
void Start () {
_origin = transform.position;
}
void Update () {
/* Get the mouse position in world space rather than screen space. */
var mouseWorldCoord = mainCamera.ScreenPointToRay(Input.mousePosition).origin;
/* Get a vector pointing from initialPosition to the target. Vector shouldn't be longer than maxDistance. */
var originToMouse = mouseWorldCoord - _origin;
originToMouse = Vector3.ClampMagnitude(originToMouse, maxDistance);
/* Linearly interpolate from current position to mouse's position. */
transform.position = Vector3.Lerp (transform.position, _origin + originToMouse, speed * Time.deltaTime);
}
}