Detect which GameObject Touched? - c#

I have 3 Game Objects. These 3 Game Objects are my right , up and left buttons.
But I have no idea to control and check which of them clicked to action on player !
Note : I can do this by creating special C# for each of game objects
by using OnMouseDown Method but I want do this in one Script file
attached to player .
and this is one of my Game Objects for Control Player

Note : I can do this by creating special C# for each of game objects
by using OnmouseDown Method but i want do this in one Script file
attached to player .
This shouldn't be a problem at-all. You can have two scripts communicate with each other.
Method 1:
Notify the PlayerController script when there is a click action from other script.
Attach to each GameObject to detect click on. It sends the GameObject that was clicked to your PlayerController script.
public class ClickDetector: MonoBehaviour
{
PlayerController playerController;
void Start()
{
playerController = GameObject.Find("GameObjectPlayerControlIsAttachedTo").GetComponent<PlayerController>();
}
void OnMouseDown()
{
//Notify our PlayerController script that there was a click
playerController.OnGameObjectClicked(this.gameObject);
}
}
Add this to your PlayerController script. It receives the GameObject that was clicked. You can compare with the GameObject name or tag. I suggest you go with a tag.
public class PlayerController: MonoBehaviour
{
public void OnGameObjectClicked(GameObject objClicked)
{
Debug.Log("There was a click from: "+objClicked.name);
if (objClicked.CompareTag("right"))
{
//Your code
}
else if (objClicked.CompareTag("left"))
{
//Your code
}
else if (objClicked.CompareTag("up"))
{
//Your code
}
}
}
Method 2:
Do everything in one script (PlayerController).
You can use a raycast. I suggest you use tag to compare which gameobject is clicked. Create 3 tags(right,left and up) from the Editor and put each GameObject to the right tag. If you don't want to use tag, you can replace the if (rayCastHit.collider.CompareTag("up")) with if (rayCastHit.collider.name=="up").
void Update()
{
//Check if Mouse Button is pressed
if (Input.GetMouseButtonDown(0))
{
//Raycast from mouse cursor pos
RaycastHit rayCastHit;
Ray rayCast = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(rayCast, out rayCastHit))
{
if (rayCastHit.collider.CompareTag("right"))
{
//Your code
}
else if (rayCastHit.collider.CompareTag("left"))
{
//Your code
}
else if (rayCastHit.collider.CompareTag("up"))
{
//Your code
}
}
}
}
EDIT:
After updating your question, you need to attach a collider to your GameObjects for raycast to work. Attach Box Collider 2D to each of the 3 GameObjects.
Also, since this is a 2D sprite, The code for Method 2 changes a little bit:
if (Input.GetMouseButtonDown(0))
{
Vector2 ray = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D rayHit = Physics2D.Raycast(ray, Vector2.zero);
if (rayHit)
{
if (rayHit.collider.CompareTag("up"))
{
}
}
}
Finally, from what you are doing, it looks like you need a Virtual JoyStick and you are current doing it wrong. The current solution should work for you but the right way to do this is with the UI system (Image component).

Related

Clicking on an Object

So I have the map in my game split into different areas. Each are made into a separate array in the Area array. I am currently stuck on being able to click on the object. When the player clicks on the object in the game the part of the map that he clicks on should pop up a certain amount and when he clicks on another part that part should pop up and the other one should do back to its original position. I am currently having that object be destroyed when I click on it, but it won't even be selected in game.
using UnityEngine;
using System.Collections;
public class AreaSelection : MonoBehaviour {
public GameObject[] Areas;
void Start()
{
Areas = new GameObject[20];
}
void Update()
{
}
void OnMouseDown()
{
Destroy(this.gameObject);
}
"OnMouseDown is called when the user has pressed the mouse button while over the GUIElement or Collider."
-- Documentation
This means that you need a Collider on the GameObject that this script is attached to. The OnMouseDown will only trigger on the GameObject it's attached to. So if you have this script on some kind of manager that doesn't have a Collider or size or anything, you won't be able to use OnMouseDown. If you'd like to go another route, which I sort of recommend, you'd relocate the logic to the Update() method sort of like this:
(from a 2d-project of mine)
```
RaycastHit2D hit;
public LayerMask mask;
Vector2 mousePos;
GameObject selectedObject;
void Update() {
// If mouse left click is pressed
if (Input.GetMouseButtonDown(0)) {
mousePos = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition);
hit = Physics2D.Raycast(mousePos, Vector2.zero, mask);
if (hit.collider != null)
{
selectedObject = hit.collider.gameObject;
}
}
}
Note that you have to set the public LayerMask in the inspector to only hit the Objects you want to hit.
With this script you should be able to send a Raycast from your screen towards your mouse and, if it hits any GameObject with the selected Layer in the LayerMask it will put that object in SelectedObject (and once you have the gameobject you can do whatever you want with it).

Changing Cube's Color on Collision with Character Controller / C#

I have recently started to learn how to code and I am really enjoying it, I am little stuck and I'd like to have your help. I have added:
A plane
Character Controller (Named 'Matt' in Hierarchy)
A Cube (Which should change color to Red on keypress and also if
Character Controller collides with the collider on cube) + The script
is attached to the cube
I would like the CUBE to change it's color if R key is pressed (which works) or if the player controller collides with the cube's collider.
Screenshot of my scene below
using UnityEngine;
using System.Collections;
public class colorChange : MonoBehaviour
{
public GameObject cube;
private Renderer rend;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
// This will get the OBJECT to CHANGE COLOR on KEY PRESS
if (Input.GetKeyDown (KeyCode.R))
GetComponent<Renderer> ().material.color = Color.red;
print ("A Key Pressed For Red Color");
}
void OnCollisionEnter (Collision col)
{
if (col.collider.name == "Matt")
{
rend.material.color = Color.yellow;
}
}
}
Here is a screenshot of the properties on the the two objects:
The complication in your collision detection is that you're using a Character Controller, which doesn't exactly work within Unity's physics simulation. As a result OnCollisionEnter() will never be called during a collision between a Character Controller and a normal collider.
It sounds like what you need is the OnControllerColliderHit() method. As per the documentation:
OnControllerColliderHit is called when the controller hits a collider while performing a Move.
However, note that it's the Character Controller that receives the event, and not the object it bumped into. So if you do revise your code to use this, you'll need to put the event on the GameObject with the controller, and detect/change the cube's renderer colour from there:
void OnControllerColliderHit(ControllerColliderHit col) {
if (col.collider.name == "cube")
{
col.gameObject.GetComponent<Renderer>().material.color = Color.yellow;
}
}
Note: Because of all the physics-related headaches associated with using Unity's Character Controller, you may actually want to create your own version of it using a Rigidbody and a capsule collider. It will take a bit more scripting, but the solution Unity offers really doesn't work well with other parts of the engine.
Hope this helps! Let me know if you have any questions.
First if you are going to detect collision then your collider on cube shouldn't be trigger. If you are going to use it as a trigger then you should use OnTriggerEnter method. Anyway attach to the character controller another collider like sphere collider make sure it's not trigger and you are good. Use GetComponent() something like this:
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "Player")
{
GetComponent<Renderer>().material.color = Color.yellow;
}
}
You need to use OnTriggerEnter instead of OnCollisionEnter
Cause your cube not really solid (cause you enabled trigger boolean in the box collider)
void OnTriggerEnter(Collider other)
{
if(other.name=="Cube")
{
transform.parent.GetComponent<Renderer>().material.color = Color.red;
}
}
also try to use Debug.Log in a lot of places to make sure you are executing or not.
That might do it.
UPDATE:
About the rend variable, since you have it private you need to assign it before executing the color changing, you'll get a NullReferenceException cause it's not assigned (the rend var)
Either make it public and assign in the inspector or do it in the Start():
rend = GetComponent<Renderer>();
Okay guys, I have managed to make it work. Below is my final code:
using UnityEngine;
using System.Collections;
public class colorChange : MonoBehaviour {
public Material color002;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
// This will get the OBJECT to CHANGE COLOR on KEY PRESS
if (Input.GetKeyDown (KeyCode.R)) {
GetComponent<Renderer> ().material.color = Color.red;
Debug.Log ("R Key Press For RED");
// This will get the OBJECT to CHANGE MATERIAL on KEY PRESS
} else if (Input.GetKeyDown (KeyCode.P)) {
GetComponent<Renderer> ().material = color002;
Debug.Log ("P Key Press For Pink Material (color002)");
}
}
// This will get the OBJECT to CHANGE COLOR if the FPS Controller collides with Cube GameObject
void OnTriggerEnter(Collider other)
{
print (other.name);
if(other.name=="FPSController")
{
GetComponent<Renderer>().material.color = Color.green;
Debug.Log ("FPS Collided with CUBE");
}
}
}
Thanks a lot for your help! Time to keep on coding :D

Changing sprite after mouse click on collider (working with many colliders and many different sprites)

I won't hide that I am new to the Unity and C#. I am trying to make mini escape game.
My problem: Changing sprites using colliders works only on one object. After clicking second object it works one time and then either the first and the second object don't work.
Description:
On the main screen I will have many items that are "clickable" and some that are "pickable". I created 2 scripts- one that close up to the clicked item, and second that return to the main view.
Main view looks like that: they are 3 colliders and each one close-up to different view. Colliders are the children of the Background. After close-up I don't want the child colliders of background to be working. Only the collider of the close-up should work.
So the question: Am I doing anything wrong? Is there any better method to change sprites after mouse click?
My code:
First script:
public class GetCloser : MonoBehaviour // shows close-up of clicked object
{
public GameObject Actual, Background;
void OnMouseDown()
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up);
if (hit.collider != null)
{
Background.SetActive(false);
Actual.GetComponent<Collider2D>().enabled = true;
Actual.GetComponent<SpriteRenderer>().enabled = true;
}
}
}
Second script:
public class ReturnTo : MonoBehaviour //hide the close-up image and return to the background
{
public GameObject Actual, Background;
void OnMouseDown()
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up);
if (hit.collider != null)
{
Background.SetActive(true);
Actual.GetComponent<Collider2D>().enabled = false;
Actual.GetComponent<SpriteRenderer>().enabled = false;
}
}
}
Last script:
public class PickUp : MonoBehaviour { //hide clicked object- works every time
// Use this for initialization
void Start () {
gameObject.GetComponent<SpriteRenderer>().enabled = true;
}
// Update is called once per frame
void OnMouseDown()
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up);
if (hit == true && hit.collider != null)
{
hit.collider.gameObject.GetComponent<SpriteRenderer>().enabled = false;
Destroy(hit.collider);
}
}
}
So if the issue is the colliders for your main screen still being active after zoom that's simply adding in your first script "zoom script" deactivating the colliders for all background or even just simply turning the gameobjects in the background off, then when you zoom back out simply turn the objects back on or colliders back on depending on which you decided to turn off.
Wait I just reread and realize after you click the first object you are no longer able to get the other objects to react any longer. Looking over your code it is probably because you are destroying the collider in your third script therefore you are no longer able to "hit" the other objects to trigger the code of a collision.

Unity - Raycast not working when more than one prefab on Scene

I created a script that uses RayCasting for detecting two Prefabs - One prefab has a tag called "target" and the second prefab has a tag called "unTarget". On click on prefab 1 with "Target" tag its supposed to increment count and when clicking on prefab 2 with "unTarget" tag its supposed to decrement the count. This seems to work when only one Prefab is in the scene. It will increment/decrement when only one is added and clicked. When both prefabs are in the Scene both prefabs will increment. I am not sure why this is happening. Any Help or Ideas? Sorry if my code is a bit messy.
using UnityEngine;
using System.Collections;
public class clicks : MonoBehaviour
{
public int score;
void Start()
{
score = 0;
}
// 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,200))
{
if (GameObject.FindGameObjectWithTag ("target"))
{
score++;
}
else
{
score--;
}
}
}
}
The GameObject.FindGameObjectWithTag method is going to look at your entire scene for an object with target as the tag. Since you have one in the scene that will always return true, if you hit something.
You need to look at the properties on the RaycastHit and pull the tag from there.
if (hit.collider.tag == "target")
{
score++;
}
else
{
score--;
}

Make object move from A to B and back again all the time

Hello and thanks for reading this.
I've created a little 2D game in Unity and I'm still very new to Unity.
I tried long and hard to search and check a guild / tutorial about how to make my "monster" move from A -> B and when he reach B then move back again. This he needs to keep doing all the time.
The Monster has a Box Collider and a Rigidbody and a "Destroyer" script so that if you run into him, you die.
I would really love to get a little help about how to create the monster movement.
Thanks alot.
This is quite simple, basically what you're looking for is a patrol feature which can be used like so:
GameObject A: (Cube, Cube Collider, Trigger = true, Disabled Mesh, Tag=PatrolPoint)
GameObject B: (Cube, Cube Collider, Trigger = true, Disabled Mesh, Tag=PatrolPoint)
GameObject C: npc that moves.
You would then need to create a script called "Patrol" that will handle the generation and ID of a patrol point. This script will be attatched to both GameObject A, and B.
using UnityEngine;
using System;
public class Patrol : MonoBehavior
{
public int patrolID;
public GameObject FindNextPoint()
{
GameObject base;
foreach(GameObject go in GameObject.FindGameObjectsWithTag("PatrolPoint"))
{
if(base == null && go.GetComponent<Patrol>().patrolID != patrolID)
{
base = go;
}
if(go.GetComponent<Patrol>().patrolID == (patrolID) + 1) {
return go;
}
}
// Return the first object found in the scene that isn't this object.
return base
}
}
Next you would need to use the OnTriggerEnter() function of unity in your script that's attatched to the player (or npc moving)-- http://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html
using UnityEngine;
using System.Collections;
public class NpcScript : MonoBehaviour
{
private Vector3 targetLocation;
void OnTriggerEnter(Collider other)
{
if(other.gameObject.tag == "PatrolPoint")
{
setWalkTo(other.gameObject);
}
}
void setWalkTo(GameObject go)
{
targetLocation = go.GetComponent<Patrol>().FindNextPoint().transform.position;
}
}
You can have as many PatrolPoints as you want, just make sure to set the PatrolID variable to something different on each of them, the character will walk to them in order.
--- You have to add your own movement code, if you need help with that, let me know. Just move the gameobjects position towards targetLocation

Categories

Resources