Unity box to Mouse issue - unity3d

I am having an issue with my code, i'm trying to move a 3D box to the variable of the position of the mouse, I need to know how to change the box's x,y,z with my mouse position script.
All im asking really, is how do I change my boxes x,y,z with a variable in another script. Thanks!
Code:
#pragma strict
public var distance : float = 4.5;
var box = Transform;
private var firstObject : cube;
function Start () {
}
function Update () {
CastRayToWorld();
}
function CastRayToWorld() {
var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var point : Vector3 = ray.origin + (ray.direction * distance);
Debug.Log( "World point " + point );
firstObject = GameObject.Find("pos").GetComponent("cube").pos = point;
firstObject.pos = point;
}

Make sure that the other object is aware of your box gameObject (lets say under the name 'adjustable'), then its simply a case of:
adjustable.transform.position = new Vector3(x, y, z)
To make sure that the object is aware of the boxes gameObject, you could make adjustable a public variable, and then manual drag the box from your scene into the field that would be created in the component on the object in question.

Related

Unity 3D fps view - objects placing at center point

I've searched around and can't seem to find a write up on the calculations I might need for placing an object onto another one without them placing halfway inside of eachother.
private void MovePlaceableObject()
{
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
Debug.DrawRay(ray.origin, ray.direction * 20f);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 15f))
{
Vector3 newPosition = hit.point;
currentPlaceableObject.transform.position = newPosition; //move object to where we have the mouse
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal); //rotation equal to the current rotation of our hitinfo, then up
}
}
private void HandeNewObjectHotkey()
{
if (Input.GetKeyDown(newObjectHotkey))
{
if(currentPlaceableObject == null)
{
currentPlaceableObject = Instantiate(placeableObjectPrefab);
//currentPlaceableObject.GetComponent<BoxCollider>().enabled = false;
}
else
{
Destroy(currentPlaceableObject); //pressing the button again will destroy current object
}
}
}
I've tried storing the object I'm looking at's size to floats for x,y,z and a vector3 for it's position, and tried fiddling around with adding those to the newPosition with the hit.point to no avail.
I've wracked my brains for about a day now, i'm terrible at math, however I know that you must need to get the current object your looking ats position or size, then factor that into your placement right?
Get the size of the object that you are looking at by accessing its collider component. You can use the bounds property of the collider to get its size.
Bounds objectBounds = hit.collider.bounds;
Calculate the center point of the object by adding half of its size to its position.
Vector3 objectCenter = hit.collider.transform.position + objectBounds.extents;
Calculate the position of the new object by adding the size of the new object to the center point of the object that you are looking at. This will place the new object on top of the other object.
Bounds newObjectBounds = currentPlaceableObject.GetComponent<Collider>().bounds;
Vector3 newObjectPosition = objectCenter + new Vector3(0, newObjectBounds.extents.y, 0);
Set the position of the new object to the calculated position.
currentPlaceableObject.transform.position = newObjectPosition;
You can also set the rotation of the new object to match the normal of the surface that it is being placed on, as you are already doing in your code.
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);

vector subtraction to move game object to another object location on unity 3d

hello I'm new to unity and game development in general, I have this task that requires me to move an object through vectors addition and subtraction, it is really simple and i understand the math behind it but I just cant understand how to use gameobject.find and transform.position of the object that has the script on it in the code.
this here is the task im trying to do :
Create two new GameObjects and position them some distance apart from each other (preferably they should have different Meshes so you can tell them apart).
Create a new script and attach it to one of the GameObjects
In this new script, make it so it can do this :
1-Find position of the other GameObject (you can use GameObject.Find to do this)
2-Use the other GameObject position and the position of itself (transform.position) to determine a direction from its position to the other GameObject.
3-Apply this direction to the transform.position of this object, so that it will immediately move to the position of the other object (this will happen in a single frame and as such appear to have “teleported”, but this is fine for now)
4-Make it so this happens on a Key Press
and this is the code I have written:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyVector3 : MonoBehaviour
{
public GameObject sphere;
private float x, y, z;
public MyVector3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public MyVector3 SubVectors(MyVector3 P, MyVector3 G)
{
MyVector3 rv = new MyVector3(0, 0, 0);
rv.x = P.x - G.x;
rv.y = P.y - G.y;
rv.z = P.z - G.z;
return rv;
}
void Start()
{
MyVector3 P = new MyVector3(transform.position);
}
1-Find position of the other GameObject (you can use GameObject.Find to do this)
In your component, use transform.position.
2-Use the other GameObject position and the position of itself (transform.position) to determine a direction from its position to the other GameObject.
Assuming you created a reference to your gameobject :
public GameObject otherGameObject;
You can do something like this :
var direction = otherGameObject.transform.position - transform.position;
3-Apply this direction to the transform.position of this object, so that it will immediately move to the position of the other object (this will happen in a single frame and as such appear to have “teleported”, but this is fine for now)
To avoid teleportation, multiply your direction by Time.deltaTime
Doc to Time.deltaTime : https://docs.unity3d.com/ScriptReference/Time-deltaTime.html
4-Make it so this happens on a Key Press
Google is your friend :)
You'll find references to the old input system and new input system.
If you are new, I suggest you to use the old one since it is easier to learn and use.
See this tutorial as example : https://medium.com/geekculture/setting-up-the-legacy-input-system-in-unity-b4d685ca6150

LineRenderer on Mesh surface

Goal: Render distance lines between two points on the surface of a mesh-based primitive (i.e. sphere, cube, etc).
Current Solution: Iteratively traverse distance line between two end points and "reverse" raycast through this point somehow. Since the distance line directly connects both vertices through the mesh, the according points on the mesh surface are required.
Ray ray = new Ray();
RaycastHit raycastHit;
ray.origin = posOnDistanceLine;
ray.direction = raycastNormal.normalized;
// Reverse ray since we can't raycast from inside the mesh
ray.origin = ray.GetPoint(1);
ray.direction = -ray.direction;
Lines are then drawn using Unity's LineRenderer which is being populated with positions of vertices whenever a change in normals (to previous raycast) is identified.
Issues:
Horrible performance (as 100 rays are cast whenever the end points move).
Solution doesn't always work and produces unexpected, jagged lines / points.
Question:
Is there a better approach to implement this?
If you want to optimize the solution, you might need to make a script for each primitive and utilize the primitive-specific math.
For example, instead of casting rays, you could simply get the radius of the mesh and put the line vertex at the radius * directionFromCenter.
Here is an example script:
[RequireComponent(typeof(LineRenderer))]
public class SurfaceLine : MonoBehaviour, IPointerClickHandler
{
[SerializeField] private float pointsPerUnit;
[SerializeField] private MeshFilter mesh;
private Vector3 start;
private Vector3 end;
private LineRenderer lineRenderer;
void Awake()
{
this.lineRenderer = this.GetComponent<LineRenderer>();
}
public void OnPointerClick(PointerEventData eventData)
{
if(eventData.button == PointerEventData.InputButton.Left)
{
this.start = this.transform.InverseTransformPoint(eventData.pointerCurrentRaycast.worldPosition);
this.Render();
return;
}
if(eventData.button == PointerEventData.InputButton.Right)
{
this.end = this.transform.InverseTransformPoint(eventData.pointerCurrentRaycast.worldPosition);
this.Render();
}
}
private void Render()
{
var distance = Vector3.Distance(this.end, this.start);
var direction = (this.end - this.start).normalized;
var numPoints = Mathf.FloorToInt(distance * this.pointsPerUnit);
numPoints = Mathf.Max(numPoints, 2);
this.lineRenderer.positionCount = numPoints;
var positions = new Vector3[numPoints];
var stepInDir = direction * (distance / (float)numPoints);
for(int i = 0; i < numPoints; i++)
{
positions[i] = this.start + i * stepInDir;
var dirFromCenter = positions[i] - this.mesh.mesh.bounds.center;
positions[i] = this.mesh.mesh.bounds.center + dirFromCenter.normalized * (this.mesh.mesh.bounds.size.x / 2.0f);
}
positions[positions.Length - 1] = this.end;
this.lineRenderer.SetPositions(positions);
}
}
This seems to perform okay in an update loop too. The down side is of course that the solution is not generic. You will need a strategy per primitive.
Alternatively you can at least leverage the pointsPerUnit concept in the script to control the resolution of your line and stick with ray casting. I think the strange artefacts you are seeing is a result of too high point density. Making the points per unit of distance consistent may have better performance too.
Here is the result for the script above:

Unable to delete clones made with instantiation function

I have made a game where I spawn in several circles which shrink over time until they are supposed to vanish. The problem is, I make all of the circles with the instantiation function. This creates "Ball(clone)" and whenever I try to use Destroy(GameObject) to get rid of one of them i get the following error.
Can't destroy Transform component of 'Ball(Clone)'. If you want to destroy the game object, please call 'Destroy' on the game object instead. Destroying the transform component is not allowed.
To be clear, the creation of the balls is handled by one script attached to an empty child, and the destruction is another script attached to the ball. They are as follows.
var Xpos : float;
var Ypos : float;
var Ball : Transform;
//Place ball
function Update ()
{
if (Input.GetMouseButtonDown(0))
{
//debugging
Xpos = Input.mousePosition.x;
Ypos = Input.mousePosition.y;
//Get mouse input and convert screen position to Unity World position
var position : Vector3 = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Instantiate(Ball,Vector3(position.x,position.y,1),Quaternion.identity);
}
}
//delete ball
#pragma strict
var Ball : Transform;
function Update ()
{
Ball.animation.Play("Shrink");
}
function Despawn ()
{
Destroy(Ball);
}
The error message says it all; you can't Destroy() a Transform. You'll have to apply that to the GameObject instead.
Changing to Destroy(Ball.gameObject); should achieve just that.

Unity3D: Two objects with the same script

I would like to associate the same script to different empty objects I just use as placeholders in the game. The aim is to exploit their positions so that when the user touch a point in the screen, close to one of these objects, a dedicate GUI appears. The problem is that though the two objects are different their scripts seem to influence each other so that when the game is running and I touch one of these two objects both the gui appears. What am I doing wrong?
....
private var check: boolean;
var topCamera : Camera;
var customSkin : GUISkin;
function Update () {
if (Input.GetMouseButtonDown(0)){
if(Input.mousePosition.x > this.transform.position.x - Screen.width*0.20 && Input.mousePosition.x < this.transform.position.x + Screen.width*20){
if(Input.mousePosition.y > this.transform.position.y - Screen.height*0.2 && Input.mousePosition.y < this.transform.position.y + Screen.height*0.2){
check = true;
}
}
}
if(check){
//the camera zooms forward
}else{
//the camera zooms backward
}
}
function OnGUI () {
if (this.check){
var w = Screen.width;
var h = Screen.height;
var bw = 0.083;
var bws = 0.001 *w;
GUI.skin = customSkin;
GUI.Box(new Rect(w*0.6,h*0.3,w*0.38,h*0.45), "Stuff");
customSkin.box.fontSize = 0.04*h;
customSkin.textField.fontSize = 0.08*h;
customSkin.button.fontSize = 0.04*h;
textFieldString = GUI.TextField (Rect (w*0.62, h*0.39, w*0.34, h*0.1), textFieldString);
if (GUI.Button (Rect (w*0.62,h*0.50, w*bw, h*0.1), "+")) {
if (this.check){
this.check=false;
}else{
this.check = true;
}
//...
}
//...
}
This is probably not working, because you are comparing apples with oranges in your Update() function. Input.mousePosition returns the the position in 2D pixel coordinates and transform.position returns the GameObject's position in 3D world coordinates.
To check if you clicked on an object, you need to attach a Collider to the game object in question and test for collisions using a Raycast in your script. Here is the relavant example from the documentation in JavaScript:
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, 100)) {
print ("Hit something");
}
The cool thing about this approach is that we are checking for collisions between the Collider and the ray. If you only want to see if you clicked near the GameObject, just make the Collider larger than the GameObject. No need for messing around with inequalities!
If your objective is to click somewhere close to the object and not only at the object, then you have some configurations (positions of those objects in space) where there are space that are close enough to both objects for their GUI to appear and therefore you need some script to decide which one is closer.
I suggest you to implement a monobehaviour that is a singleton that would track those clicks and measure the distance of all objects, to get the closest.
Reading again your post, I think you want to get the GUI just when you click at the object, and when you do this you get both GUIs. I think that's happening because wrong calculation of the area that makes check to go true.
Can you give more details? Is there some space where there shouldn't have GUI messages when clicked, or is everything filled by those objects?