- Home /
Can't get Instantiated Object to Follow Mouse Position(Solved)
I'm trying to make it so as when I click a GUI button an object is instantiated at the mouse's position AND follows the mouse position around the screen. Unfortunately all it is doing is instantiating the Object at the mouse position at the moment I click on the GUI button and is not following the mouse around.
using UnityEngine;
using System.Collections;
public class SatCamUpdatedGUI : MonoBehaviour
{
RaycastHit hit;
private float raycastLength = 1000;
public Texture HQBtnTex; //Texture for the HQ Button
public GameObject HQPrefab; //Actual HQ prefab
public GameObject FakeHQ; //Mouse Pointer HQ Prefab
private GameObject ChosenPrefab;
void OnGUI()
{
if(GUI.Button(new Rect(26,26,72,72),HQBtnTex))
{
GameObject ChosenPrefab = FakeHQ;
Debug.Log("HQ Chosen");
PlaceHQPrefab();
}
}
public void Update()
{
}
public void PlaceHQPrefab()
{
//ChosenPrefab = Instantiate(Resources.Load("FakeHQ")) as GameObject;
GameObject ChosenPrefab = Instantiate(FakeHQ, hit.point, Quaternion.identity) as GameObject;
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if(Physics.Raycast(ray, out hit, raycastLength))
{
Debug.Log(hit.collider.name);
if(hit.collider.name == "Terrain")
{
ChosenPrefab.transform.position = hit.point;
}
}
}
}
I'm basing my script on an earlier script I was using that simply had an object follow the mouse continuously. -
using UnityEngine;
using System.Collections;
public class MousePointer : MonoBehaviour
{
RaycastHit hit;
private float raycastLength = 1000;
void Start()
{
}
void Update()
{
GameObject Target = GameObject.Find("Target");
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if(Physics.Raycast(ray, out hit, raycastLength))
{
Debug.Log(hit.collider.name);
if(hit.collider.name == "Terrain")
{
Target.transform.position = hit.point;
}
}
Debug.DrawRay(ray.origin, ray.direction * raycastLength, Color.yellow);
}
}
I think (please correct me if I'm wrong) that the reason the object doesn't follow the mouse is that it isn't using the void Update() and therefor the object position isn't being updated.
However with the script I'm writing when I use the void Update() function I get objects repeatedly instantiated over and over until the screen is full of them...lol
How do I change it so I get just a single object Instantiated AND that object follows my mouse?
Any suggestions please guys ???
O$$anonymous$$, not really sure if this is a step in the right direction(or not) but its different. Have adjusted the script to this -
using UnityEngine;
using System.Collections;
public class $$anonymous$$ouseInstantiateAndFollow : $$anonymous$$onoBehaviour
{
RaycastHit hit;
private float raycastLength = 1000;
public Texture HQBtnTex; //Texture for the HQ Button
public GameObject HQPrefab; //Actual HQ prefab
public GameObject FakeHQ; //$$anonymous$$ouse Pointer HQ Prefab
private GameObject ChosenPrefab;
void OnGUI() //Places the Object in the World
{
if(GUI.Button(new Rect(26,26,72,72),HQBtnTex))
{
GameObject ChosenPrefab = Instantiate(FakeHQ, hit.point, Quaternion.identity) as GameObject;
Debug.Log("HQ Chosen");
}
}
void Update() //Allows Object to Follow $$anonymous$$ouse like in Original Script
{
GameObject Target = ChosenPrefab;
//GameObject Target = GameObject.Find("ChosenPrefab");
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if(Physics.Raycast(ray, out hit, raycastLength))
{
Debug.Log(hit.collider.name);
if(hit.collider.name == "Terrain")
{
Target.transform.position = hit.point;
}
}
Debug.DrawRay(ray.origin, ray.direction * raycastLength, Color.yellow);
}
}
But I'm now getting a compile error -
NullReferenceException: Object reference not set to an instance of an object $$anonymous$$ouseInstantiateAndFollow.Update () (at Assets/Scripts/$$anonymous$$ouseInstantiateAndFollow.cs:40)
Am I right in thinking that line 40 is throwing that error because the Update function is immediately looking for the game object? And obviously the object will not be there until the player clicks the GUI button ?
If so... how do I make it wait until after the player has clicked the button ?
???
Answer by hexagonius · Feb 11, 2015 at 07:45 AM
I recommend you separating the scripts. One script for the Gui, the update on the prefab directly. Right now update is running without testing chosenprefab for null, which it is until you press the gui button.
O$$anonymous$$, I tried separating the scripts.
If I place the object into the scene and then play it happily follows the mouse position wherever I point (using this script)
using UnityEngine;
using System.Collections;
public class $$anonymous$$ousePointerUpdated : $$anonymous$$onoBehaviour
{
public GameObject Target;
RaycastHit hit;
private float raycastLength = 1000;
void Start()
{
}
void Update()
{
GameObject Target = GameObject.Find("HQFake");
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if(Physics.Raycast(ray, out hit, raycastLength))
{
Debug.Log(hit.collider.name);
if(hit.collider.name == "Terrain")
{
Target.transform.position = hit.point;
PlaceHQPrefab
}
}
Debug.DrawRay(ray.origin, ray.direction * raycastLength, Color.yellow);
}
}
If I instantiate the object into the scene using the GUI button (this script)
using UnityEngine;
using System.Collections;
public class $$anonymous$$ouseInstantiateAndFollow : $$anonymous$$onoBehaviour
{
RaycastHit hit;
private float raycastLength = 1000;
public Texture HQBtnTex; //Texture for the HQ Button
public GameObject HQPrefab; //Actual HQ prefab
public GameObject FakeHQ; //$$anonymous$$ouse Pointer HQ Prefab
public GameObject ChosenPrefab;
void OnGUI()
{
if(GUI.Button(new Rect(26,26,72,72),HQBtnTex))
{
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if(Physics.Raycast(ray, out hit, raycastLength))
{
if(hit.collider.name == "Terrain")
{
GameObject ChosenPrefab = Instantiate(FakeHQ, hit.point, Quaternion.identity) as GameObject;
}
}
}
}
}
The object just sits there and does not move. Then when/if I move the mouse the game crashes and I get this error -
NullReferenceException: Object reference not set to an instance of an object $$anonymous$$ousePointerUpdated.Update () (at Assets/Scripts/$$anonymous$$ousePointerUpdated.cs:29)
???
Remove the Target Reference from the $$anonymous$$ousePointerUpdated script. Since you ARE that GameObject, just manipulate transform.position. That's it. So line 21 is obsolete, remove Target from line 31 and just use transform.position.
P.S. In the $$anonymous$$ouseInstantiateAndFollow Script you don't need to save the instantiate to ChosenPrefab, since you're not doing anything with it. Just remove the assignment (this is optional)
Answer by lordlycastle · Feb 11, 2015 at 08:45 AM
The reason for player getting instantiated repeatedly when you call the PlaceHQPrefab function from the update is because, you didn't put it inside an if condition; that checks if the mouse was clicked or not. So instead of calling PlaceHQPrefab directly from OnGUI you could use a bool variable to indicate the button was clicked.
bool buttonClicked = false;
float speed = 5.0f;
GameObject ChosenPrefab;
public void OnGUI(){
if (GUI.Button(new Rect(26,26,72,72),HQBtnTex)){
//Do some stuff to the button like change colour when clicked, or display player count.
buttonClicked = true;
}
}
void Update(){
if (Input.GetMouseButtonDown(0) && buttonClicked){
print("Left clicked!");
PlaceHQPrefab();
buttonClicked = false;
}
if (ChosenPrefab != null){
//Temp code to make the player follow the current mouse position
ChosenPrefab.transform.position = Vector3.Lerp(ChosenPrefab.transform.position, Input.mousePosition, speed * Time.deltaTime);
}
}
Obviously you shouldn't use Lerp function to move the player, it might be jittery. Use the move function on the character controller.
P.S. in your comment, the error is probably caused because you didn't instantiate the game object and tried to change it's transform position, you can easily avoid that by using
if(gameObject != null){
print(gameObject.name + "does exist, and it's position is:" + gameObject.transform.position);
}