So I have 2 objects on my imageTarget and i added a box collider to both of them. I also added a different tag to them. I want it so that if you click on one of them it brings you to a different scene with info about that object.
This is my code:
using System.Collections;using System.Collections.Generic;
using UnityEngine;
using Vuforia;
using System.IO;
public class ObjectInfo : MonoBehaviour
{
public GameObject Eagle;
public GameObject LibertyStatue;
// Use this for initialization
void Start ()
{
Eagle = GameObject.Find ("Eagle");
LibertyStatue= GameObject.Find ("LibertyStatue");
//Eagle.SetActive (true);
//LibertyStatue.SetActive (true);
}
// Update is called once per frame
void Update ()
{
if (Input.GetMouseButtonDown (0))
{
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if(hit.collider.tag == "Eagle");
{
ChangeScene ("EagleInfoScene");
}
if(hit.collider.tag == "LibertyStatue");
{
ChangeScene ("LibertyStatueInfoScene");
}
}
}
}
public void ChangeScene (string a)
{
Application.LoadLevel (a);
}
}
When i first added only one of the objects it worked fine, now after adding a new object and a new scene, both objects change to the new scene. So clicking both the eagle and liberty statue changes the scene to LibertyStatueInfoScene. Is there a way to fix this?
Solved: Wow im really stupid, the issue was that i had semicolons after my if statements, it didn't give me an error so i never noticed it.
Solution: I didnt notice the semicolons after the if statements, removing them solves it. Strangely it didn't give me an error.
Related
I started making a 2d game, where an Individual Prefab Instance has to change color after being touched. I'm new to programming in C# and I've scoured the internet for hours but I still can't find an answer which works. I tried adding GetComponent<Renderer>().material.color = Color.red; to the script on my prefab but it changes the color of all instantiated prefabs. My Unity version is 2019.2.3f1. Please help me.
Here's the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchDetector : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.transform.name == "square")
{
Destroy(gameObject);
print("TOUCHED");
GetComponent<Renderer>().material.color = Color.red;
}
}
}
}
}
Your problem lies in
GetComponent<Renderer>().material.color = Color.red;
Each of your instances of this script is running that method simultaneously so the Raycast and hit is processed on all of them.
In general it makes little sense to me that you do Destroy(gameObject) and right after it try to access GetComponent<Renderer> of the object you just destroyed ...
It is a bit unclear what you wanted to do but I guess it was something like
if (hit.transform.name == "square")
{
print("TOUCHED");
hit.gameObject.GetComponent<Renderer>().material.color = Color.red;
}
Which only colors the object that was hit. You would also only need exactly one instance of this component in your scene!
A way better way would be that each item detects the click itself! You can do this e.g. implementing the IPointerDownHandler interface like
public TouchDetector : MonoBehaviour, IPointerDownHandler
{
public void OnPointerDown(PointerEventData data)
{
Debug.Log("I was touched!", this);
GetComponemt<Renderer>().material.color = Color.Red;
}
}
This would go on each object that should detect a click/touch.
Notes:
In newer versions UI was moved to a Package in the PackageManager, make sure it is installed.
According objects either have to be UI or require a Collider and on the Camera a PhysicsRaycaster component.
Hi guys,
I am working in Unity (C#) and I have a problem. I have a cube called littleOne that is falling down from start position and another cube that destroys the first cube OnTriggerEnter. When the first cube collides with "destroyer" cube, I want to bring it back to the start position. All game objects are attached correctly to the script. This is my solution:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyObject : MonoBehaviour
{
public GameObject littleOne;
public Vector3 startPoint;
void Start()
{
startPoint = littleOne.transform.position;
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.name == "littleOne") {
other.gameObject.transform.position = startPoint; //*not working
//littleOne.transform.position = startPoint; //*not Working
}
}
}
Lines that has symbol * does nothing, well with these lines I have a problem. I was searching for solution and I tried this way, but nothing happens.
EDIT: PROBLEM SOLVED: I have solved the problem. This code I have moved to a script with falling operation. It was issue in multiple related script to a object. Thank you for recommendations!
Other object and littleOne are referring to the same object which you are destroying:
Dont destroy it:
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.name == "littleOne")
{
littleOne.transform.position = startPoint;
}
}
I have made a Raycast that goes from my camera to the point of the object clicked. However, I am trying to make an object (in this case a bullet) to fly along the path of the ray. At the moment it flies straight forwards from the camera no matter where on the object you click because of the vector 3. How would I get it to follow the Ray?
C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RaycastShot : MonoBehaviour {
public Camera camera;
private Ray ray;
private RaycastHit hit;
public GameObject bullet;
private GameObject createBullet;
private Collider collider;
void Update () {
if (Input.GetMouseButtonDown (0)) {
ray = camera.ScreenPointToRay (Input.mousePosition);
createBullet = Instantiate (bullet, camera.transform.position, bullet.transform.rotation);
createBullet.AddComponent<Rigidbody>();
createBullet.GetComponent<Rigidbody>().AddRelativeForce (new Vector3(0, 1500, 0));
createBullet.GetComponent<Rigidbody>().useGravity = false;
collider = createBullet.GetComponent<Collider> ();
Destroy (collider);
if (Physics.Raycast (ray, out hit)) {
}
}
Debug.DrawLine (ray.origin, hit.point, Color.red);
}
}
You would want to use ray.direction property instead of (0,1500,0) as the direction of the force.
The add force should occur in FixedUpdate, and should only occur if the Ray hits something. Where you have it now is probably not the best spot.
Of course, make sure the bullet gets instantiated at the camera's location first.
Ray.direction gives you the vector3 direction of the ray object. If you need the distance at which it hit, you could also use ray.distance.
Edit: I'm near my computer now, so here's a more detailed answer relating to your comments.
First off: Here's the way I set up the test Project:
I Created a prefab bullet. This is just a sphere with a rigidbody, with my "BulletController" script attached to it. The point of prefabs is to avoid all of those lines where you have to add components. For testing purposes I set the rigibody to ignore gravity and its mass to 0.1.
Next, I created the BulletController script, which will be attached to the bullet prefab.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletController : MonoBehaviour {
Rigidbody rb;
public float bulletForce;
bool firstTime = false;
Vector3 direction;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody> ();
}
public void SetDirection (Vector3 dir) {
direction = dir;
firstTime = true;
}
void OnCollisionEnter () {
//code for when bullet hits something
}
void FixedUpdate () {
if (firstTime) {
rb.AddForce (direction * bulletForce);
firstTime = false;
}
}
}
This script is is charge of controlling bullets. The (later on) script that will create the bullets doesn't really care what happens to them afterwards, since its job is just to create bullets. This BulletController script is in charge of dealing with bullets once they're created.
The main parts are the SetDirection method which tells the bullet which direction to travel in. Also it adds a one-time force in its FixedUpdate method that pushes it in the direction you just set. FixedUpdate is used for physics changes like adding forces. Don't use Update to do this kind of thing. It multiplies the force by a force that you set called "bulletForce".
Finally the BulletListener Script, which is simply attached to an empty game object in the scene. This script is in charge of listening for mouse clicks and creating bullets towards them.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletListener : MonoBehaviour {
public Camera mainCamera;
public BulletController bulletPrefab;
void Update () {
if (Input.GetMouseButtonDown (0)) {
//create ray from camera to mousePosition
Ray ray = mainCamera.ScreenPointToRay (Input.mousePosition);
//Create bullet from the prefab
BulletController newBullet = Instantiate (bulletPrefab.gameObject).GetComponent<BulletController> ();
//Make the new bullet start at camera
newBullet.transform.position = mainCamera.transform.position;
//set bullet direction
newBullet.SetDirection (ray.direction);
}
}
}
In the inspector for this empty game object, I added this script, and then dragged the camera, and the bulletPrefab into the appropriate fields. Be sure to drag the prefab from the FOLDER, not from the SCENE. Since this will use the prefab, not an object in the scene.
Now click around and you'll see the bullets flying! Note that using a low force is good to test, and then increase it later.
The main things to take away from this is to split up your logic. A script should only be in charge of one thing. For example, your enemies might also fire bullets. You can now reuse your bulletController script for those bullets as well. Also, say you have different sized or shaped bullets, you can just drag the bulletcontroller script onto the different prefabs you've made for your bullets. This will not affect your listener script which will still create bullets where you click.
If you have the end point then you can move along the vector with MoveTowards:
Vector3 target = hit.point;
StartCoroutine(MoveAlong(target));
private IEnumerator MoveAlong(Vector3 target){
while(this.transform.position != target){
this.transform.position = MoveTowards(this.transform.position, target, step);
yield return null;
}
}
The script is attached to the ThirdPersonController and once i'm running the game the head is looking down like the neck is broken. Something scary.
using UnityEngine;
using System.Collections;
public class MoveObjects : MonoBehaviour {
bool isSpinning;
// Use this for initialization
void Start()
{
isSpinning = true;
}
// Update is called once per frame
void Update()
{
MovePlayerWithMouse();
}
private void MovePlayerWithMouse()
{
if (isSpinning == true)
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit) && hit.collider.name != "ThirdPersonController")
{
transform.LookAt(hit.point);
}
else
{
transform.LookAt(ray.GetPoint(100)); //the number here is compltely arbitrary
}
}
}
}
This is a screenshot showing the player head when running the game:
Because you don't have an IK pass on the model. LookAt() makes the transform rotate toward the point you want to look, and since it has not an IK , it just make that fun recoil.
I'm having a bit of trouble getting the Vector3 wayPointPosition to my other script called Walking and changing it into the Transform target. My troubles lie in the fact that I'm trying to grab this dynamic variable from WayPointPositioner (it changes depending on what object is clicked in the stage and whether the player overlaps with this waypoint) and import and use it in another script.
Below is the code I'm using.
WayPointPositioner
using UnityEngine;
using System.Collections;
public class WayPointPositioner : MonoBehaviour {
public Vector3 wayPointPosition = Vector3.zero;
private bool checkPlayerWaypointCollision;
void Start()
{
}
void OnTriggerStay2D (Collider2D other)
{
// Check if collision is occuring with player character.
if (other.gameObject.name == "Player")
{
checkPlayerWaypointCollision = true;
}
else
{
checkPlayerWaypointCollision = false;
}
}
//Check if object is clicked
void OnMouseDown ()
{
// If its the player, then return a new position for the player to move to for walking
// Else debug that its not so
if (checkPlayerWaypointCollision == false)
{
Debug.Log ("Object not colliding and retrieving position");
Debug.Log (wayPointPosition);
Debug.Log (gameObject.name);
wayPointPosition = new Vector3 (transform.position.x, transform.position.y, 10);
wayPointPosition = Camera.main.ScreenToWorldPoint(wayPointPosition);
}
else
{
Debug.Log ("Object is colliding, no movement needed");
}
}
}
Walking
using UnityEngine;
using System.Collections;
public class Walking : MonoBehaviour {
public Transform target;
public WayPointPositioner wayPointPosition;
public bool walkingAnimation = false;
private Animator anim;
void Awake ()
{
anim = GetComponent<Animator> ();
wayPointPosition = GameObject.FindGameObjectWithTag ("Waypoint").GetComponent<WayPointPositioner> ();
}
void Start ()
{
}
void Update ()
{
Debug.Log ("This is in Walking, WPP =" + wayPointPosition);
}
}
As you can see I'm trying to import the wayPointPosition from the seperate class which is attached to the gameobjects called "Waypoint" (In my current layout those are empty objects with circle colliders to check if they have been clicked). However when I run this, I am not getting my Vector, but I'm getting the name of the last waypoint in the hierarchy (I have currently 6 waypoints which can be clicked) and not a Vector.
I hope someone is able to help me / point out my mistake. I'm still learning C# so I might've made a strange / odd assumption which isn't working.
Kind regards,
Veraduxxz.
It looks like invoking GameObject.FindGameObjectWithTag("Waypoint").GetComponent<WayPointPositioner>(); retrieves a component from the game object which matches the specified tag, as well as a type argument T which derives from MonoBehavior.
Calling this should actually give you an instance of your WayPointPositioner class, which you can then pass to whichever methods you want, and interact with its Vector3 however you would like.