Get 2D position of a 3D object when it follows another object? - c#

How do I get 2D position of a 3D object (ie. z axis should be 0) when this object is following another 3D object?
So far I have tried the below one line code but the z axis does not remain 0 since it follows another object it keeps fluctuating. Any solutions?
public GameObject Car;
public GameObject Icon;
// Update is called once per frame
void Update ()
{
Icon.transform.position = Vector3.MoveTowards(Car.transform.position, Car.transform.position, 0);
}

Icon.transform.position = Vector3.MoveTowards(Car.transform.position, Car.transform.position, 0);
this does absolutely nothing ... first of all you are move between the same positions and secondly with a speed = 0... so basically this equals
Icon.transform.position = Car.transform.position;
What you wanted to do instead is eliminating the z component of the position vector so e.g. something like
Icon.transform.position = new Vector3(Car.transform.position.x, Car.transform.position.y, 0);
or a little trick: you can typecast it to Vector2 which makes it "forget" the z value. It is than implicitely typecasted back to Vector3 with z=0
Icon.transform.position = (Vector2) Car.transform.position;

You just put the position in a local variable and set z to 0.
public GameObject Car;
public GameObject Icon;
// Update is called once per frame
void Update () {
Vector3 pos3d = Car.transform.position;
pos3d.z = 0;
Icon.transform.position = pos3d;
}

Related

Unity set Script as AudioSource

Is there a way in Unity to set a Script as an AudioSource?
I have a Script which produces Sound, i now want to Visualize this, but with GetComponent i only get a null value.
I have tried with GetComponent but for that i need to set the Script as the Source, and it already worked with AudioListeners but i need the AudioSource to also visualize it. I have used several online tutorials, but no one uses a Script as Source.
I can only see one solution left, which i want to avoid ,which would be writing the data from the AudioSource in a file, and generating the Visualization that way.
Edit: I have tried what DareerAhmadMufti suggested:
Sadly it still doesn't work.
public class AudioGaudioGenerator : MonoBehaviour
{
private Graph graph;
public AudioSource _audioSource;
float[] farr = new float[4096];
void Start()
{
graph = this.GetComponentInChildren<Graph>();
_audioSource = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
GetSpectrumAudioSource();
if (graph.showWindow0)
{
graph.SetValues(farr);
}
}
void GetSpectrumAudioSource()
{
_audioSource.GetOutputData(farr, 0);
}
This is the Script for the AudioGenerator
You want to use a script for audio visualization, but you only get a null value using the "GetComponent" method. You can create an empty object in the scene with position coordinates (0,0,0) and rename it Audio Visualization, and add LineRenderer and AudioSource components to it.Create a red shader and assign it to LineRenderer.
Create a cube, then create a green shader and assign it to the cube, drag it into a prefab cube.
write scripts:
public class AudioVisualization : MonoBehaviour
{
AudioSource audio;//Sound source
float[] samples = new float[128];//The length of the array to store the spectrum data
LineRenderer linerenderer;//Draw line
public GameObject cube;//cube prefab
Transform[] cubeTransform;//Position of cube prefab
Vector3 cubePos;//The middle position, used to compare the cube position with the spectral data of this frame
// Use this for initialization
void Start()
{
GameObject tempCube;
audio = GetComponent<AudioSource>();//Get the sound source component
linerenderer = GetComponent<LineRenderer>();//Get the line drawing component
linerenderer.positionCount = samples.Length;//Set the number of segments of the line segment
cubeTransform = new Transform[samples.Length];//Set the length of the array
//Move the gameobject mounted by the script to the left, so that the center of the generated object is facing the camera
transform.position = new Vector3(-samples.Length * 0.5f, transform.position.y, transform.position.z);
//Generate the cube, pass its position information into the cubeTransform array, and set it as the child object of the gameobject mounted by the script
for (int i = 0; i < samples.Length; i++)
{
tempCube=Instantiate(cube,new Vector3(transform.position.x+i,transform.position.y,transform.position.z),Quaternion.identity);
cubeTransform[i] = tempCube.transform;
cubeTransform[i].parent = transform;
}
}
// Update is called once per frame
void Update()
{
//get spectrum
audio.GetSpectrumData(samples, 0, FFTWindow.BlackmanHarris);
//cycle
for (int i = 0; i < samples.Length; i++)
{
//Set the y value of the middle position according to the spectrum data, and set the x and z values ​​according to the position of the corresponding cubeTransform
//Use Mathf.Clamp to limit the y of the middle position to a certain range to avoid being too large
//The more backward the spectrum is, the smaller
cubePos.Set(cubeTransform[i].position.x, Mathf.Clamp(samples[i] * ( 50+i * i*0.5f), 0, 100), cubeTransform[i].position.z);
//Draw a line, in order to prevent the line from overlapping with the cube, the height is reduced by one
linerenderer.SetPosition(i, cubePos-Vector3.up);
//When the y value of the cube is less than the y value of the intermediate position cubePos, the position of the cube becomes the position of the cubePos
if (cubeTransform[i].position.y < cubePos.y)
{
cubeTransform[i].position = cubePos;
}
//When the y value of the cube is greater than the y value of the cubePos in the middle position, the position of the cube slowly falls down
else if (cubeTransform[i].position.y > cubePos.y)
{
cubeTransform[i].position -= new Vector3(0, 0.5f, 0);
}
}
}
}
Hook the script on Audio Visualization and assign the prefab cube to the script. Import an audio resource and assign the audio resource to the audiosouce component.
The playback effect is as follows
You cannot use a script as an AudioSource. There is already an AudioSource script. If an object contains the AudioSource script, then you are able to access with GetComponent<AudioSource>(). But it ust already be on the object.
Your question is quite ambiguous. you can't use your custom script as AudioSource, as it is a sealed class.
If you want to get access data of the audioClip or audioSource, add AudioSource component to same object in which your script is attached. like:
make a public AudioSource variable in your script and assign the AudioSource component, as shown above in screenshot.
In this way you will be able to access the data you want in you custom scripts via that variable.

Moving Prefabs, Unity Spawner, Move Position

I have one problem. I want my prefabs to spawn every time my player picks them up. I did research on Google and YouTube and I tried to use the random function and instantiate. I don't know how to use them. I wrote this code I saw on YouTube and my prefab Sphere moves like 1cm to z position. I want to every time when I pick up object or my player go to spawn more of this on the z position. How do I do this?
My smaller script:
public GameObject Sphere;
public float zrange;
// Use this for initialization
void Start () {
RandomPosition();
}
void RandomPosition()
{
zrange = Random.Range(0f, 2f);
this.transform.position = new Vector3(0, 0, zrange);
}
You achieve that by not messing with the x and y values (your code sets them both to 0).
Vector3 p = transform.position;
p.z = zrange;
transform.position = p;
This assumes that your code to instantiate the object is already correctly placing the object. If not, more information is needed.

Why gameObject get such positions in Unity?

I want to create 2d game.
Structure of objects
[]
"View" present a square where everything happens.
"Initial" This is the same square with a mask
"SquareList" is empty panel.
Why am I doing this?
I created a script where when I click on the screen, a new square is added to the SquareList. SquareList is the parent. I created a script to determine the position of the cursor.
createPos = new Vector2 (Input.mousePosition.x, Input.mousePosition.y);
Next, I want to set for new object position = cursor position.
Cursor.position equivalent = (562,1134 / 242.6486)
But the new object get position (94931.29 / 103365.6 / -17280)
But if I set position of new object to = new Vector(0,0);
Then everything is fine
What is the problem?
Input.mousePosition returns position in pixel-coordinate. You have to use Camera.main.ScreenToWorldPoint to convert it to world position then assign that to the object. If 3D Object, add an offset to it before converting with ScreenToWorldPoint.
public GameObject prefab;
public float offset = 10f;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Vector3 clickPos;
clickPos = Input.mousePosition;
clickPos.z = offset;
clickPos = Camera.main.ScreenToWorldPoint(clickPos);
GameObject obj = Instantiate(prefab, clickPos, Quaternion.identity);
}
}
Hello nameless brother/sister! I believe you are seeing this issue because your game object's coordinates are affected by its parent's coordinates. You may need to use localPosition to find more relative coordinates.
More info: https://docs.unity3d.com/ScriptReference/Transform-localPosition.html

Issues with transform.Rotate in Unity

I have been working on programming a graph in Unity that rotates based on head movement. I have been having multiple issues with the rotation aspect of it.
A sample of the Autowalk class, which I am using to find the angle that the graph needs to rotate based on where the user is facing:
public class AutoWalk : MonoBehaviour {
//VR head
private Transform vrHead;
//angular displacement from normal
public float xAng, yAng, zAng;
//previous values
public float xOrig, yOrig, zOrig;
// Use this for initialization
void Start () {
//Find the VR head
vrHead = Camera.main.transform;
//finding the initial direction
Vector3 orig = vrHead.TransformDirection(Vector3.forward);
xOrig = orig.x;
yOrig = orig.y;
zOrig = orig.z;
}
// Update is called once per frame
void Update () {
//find the forward direction
Vector3 forward = vrHead.TransformDirection(Vector3.forward);
float xForward = forward.x;
float yForward = forward.y;
float zForward = forward.z;
//find the angle between the initial and current direction
xAng = Vector3.Angle(new Vector3(xOrig, 0, 0), new Vector3(xForward, 0, 0));
yAng = Vector3.Angle(new Vector3(0, yOrig, 0), new Vector3(0, yForward, 0));
zAng = Vector3.Angle(new Vector3(0, 0, zOrig), new Vector3(0, 0, zForward));
//set new original angle
xOrig = xAng;
yOrig = yAng;
zOrig = zAng;
}
From there I go to the ReadingPoints class, which contains all of the points on the graphs (spheres) and axes (stretched out cubes):
public class ReadingPoints : MonoBehaviour {
// Update is called once per frame
void Update () {
float xAngl = GameObject.Find("GvrMain").GetComponent<AutoWalk>().xAng;
float yAngl = GameObject.Find("GvrMain").GetComponent<AutoWalk>().yAng;
float zAngl = GameObject.Find("GvrMain").GetComponent<AutoWalk>().zAng;
if ((xAngl != prevXAngl) || (yAngl!=prevYAngl) || (zAngl!=prevZAngl))
{
//rotate depending on the angle from normal
foreach (GameObject o in allObjects)
{
o.transform.Rotate(new Vector3(xAngl, yAngl, zAngl), Space.World);
prevXAngl = xAngl;
prevYAngl = yAngl;
prevZAngl = zAngl;
}
}
allObjects, as the name implies, contains the points and the axes.
Anyway, the first issue that is upon running the program is that the graph appears to be torn apart.
How the graph is supposed to look (this is what it looks like when o.transform.Rotate(...) is commented out)
Here is how it actually looks :( Also, the graph does not rotate when I move, and I have no idea why (I thought I might be using the Rotate function improperly but perhaps I also didn't find the correct angles?). Any ideas of what went wrong are much appreciated, thank you!
First of all I think you should start using Quaternions (https://docs.unity3d.com/ScriptReference/Quaternion.html)
Secondly; while you rotate a object with a Camera attached its line of view will change and eventually the object(Graph) will be out of view. If you want as much of the full graph as possible to remain in view of camera as long as possible. You should give the Quaternion of the graph the opposite rotation of that applied to your Camera or the object it is attached to.
Make sure your all elements of your graph are children of a central gameobject in your graph, and only manipulate that point.

Create scipt to allow dragging and snapping

I have a script that lays out prefabs, on a surface, by creating an array of vectors. Each array contain 14 vectors, which produce evenly spaced locations, on a plane.
public List<Vector3> handEastVectorPoints = new List<Vector3>();
public List<Vector3> handSouthVectorPoints = new List<Vector3>();
public List<Vector3> handNorthVectorPoints = new List<Vector3>();
public List<Vector3> handWestVectorPoints = new List<Vector3>();
Then when a prefab is instantiated, my code grabs the correct vector, from the correct array, and add the prefab, like this:
public IEnumerator addTileInHand(GameObject tile, Vector3 v, float time, Vector3 rotationVector, int pos)
{
Quaternion rotation = Quaternion.Euler(rotationVector);
GameObject newTile = Instantiate(tile, v, rotation);
tile.GetComponent<TileController>().canDraw = true;
tile.GetComponent<TileController>().gameStatus = getCurrentGameState();
tile.GetComponent<TileController>().currentTurn = sfs.MySelf.Id;
PlayersHand[pos] = newTile;
yield return new WaitForSeconds(time);
}
When this function is called, its passed a vector, which comes from the above array. The prefab is created, and added to an array of gameObjects.
What I now want to do is allow the player to drag and drop the to various "hot spots", as defined in the first set of arrays (again, their are 14 vectors) and drop them. If there is already a prefab in that position, I would want it to snap to the new position that just opened up. If the tile is dropped anywhere else, it should snap back to its original location. I also just want the object to be dragged either left or right, no need to up and down or up through the Y axis.
Can anyone point me to similar script that might help or provide assistance?
thanks
Edit: Draggable Script Got this working. You can only drag on the X axis, but for my use case, this works.
public class DraggableObject : MonoBehaviour {
private bool dragging = false;
private Vector3 screenPoint;
private Vector3 offset;
private float originalY;
void Start()
{
originalY = this.gameObject.transform.position.y;
}
void OnMouseDown()
{
screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, originalY, screenPoint.z));
}
void OnMouseDrag()
{
Vector3 cursorPoint = new Vector3(Input.mousePosition.x, originalY, screenPoint.z);
Vector3 cursorPosition = Camera.main.ScreenToWorldPoint(cursorPoint) + offset;
transform.position = cursorPosition;
dragging = true;
}
void OnMouseUp()
{
dragging = false;
}
}
I have done a similar thing for my game. This is quite easy. Follow the following steps and let me know if you have any further queries:
Write a script (let's say HolderScript ) and add a boolean occupied to it. Add an OnTriggerEnter (A Monobehaviour function) to the script and update the boolean accordingly:
Case 1 - Holder is not occupied - Make boolean to true and disable Colliders if the prefab is dropped there, else do nothing.
Case 2 - Holder is occupied - if occupied prefab is removed then in OnTriggerExit function make boolean to false and enable colliders.
Write a Script (let's say DraggableObject) and set the drag and isDropped boolean accordingly and you can use Lerp function for snapping back.
Attach the holder script to the droppable area and DraggableObject script to the draggable objects.
This should solve your issue.

Categories