I have a 3d Unity game with few 3d objects in worldspace. I have a reticle in cameraspace. When reticle crosses each 3d object, I have a pointer -enter and pointer-exit event written. when mobile phone is moved the reticle moves, but the 3d object stays in worldspace. The reticle is not functioning as pointer. Although the touch event is working, I could not make reticle as a pointer. I have added physics raycast with the camera.
What mistake I am doing?
Okay, so you are trying to use a UI.Selectable event (Selectable.OnPointerEnter) on a non-UI object.
Assuming you have the reticle position in screen space, I highly recommend using Physics.Raycast from the a script attached to the Camera object, though it could simply reference the camera instance instead. We can use this combined with a "hitObject" to trigger custom reticle enter/exit/hover events as seen below:
CameraPointer.cs:
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Camera))]
public class CameraPointer : MonoBehaviour {
private GameObject hitObject = null;
private Vector3 reticlePosition = Vector3.zero;
private Camera camera;
void Awake() {
camera = GetComponent<Camera>();
}
// Update is called once per frame
void Update () {
// TODO: Replace with reticle screen position
reticlePosition = Input.mousePosition;
// Raycast variables
Ray ray = camera.ScreenPointToRay(reticlePosition);
RaycastHit hit;
// Raycast
if (Physics.Raycast(ray, out hit)) {
if (hitObject != hit.transform.gameObject) {
if (hitObject != null) {
hitObject.SendMessage("OnReticleExit"); // Trigger "OnReticleExit"
}
hitObject = hit.transform.gameObject;
hitObject.SendMessage("OnReticleEnter"); // Trigger "OnReticleEnter"
} else {
hitObject.SendMessage("OnReticleHover"); // Trigger "OnReticleHover"
}
} else {
if (hitObject != null) {
hitObject.SendMessage("OnReticleExit"); // Trigger "OnReticleExit"
}
hitObject = null;
}
}
}
MyObject.cs:
using UnityEngine;
using System.Collections;
public class MyObject : MonoBehaviour
{
// Custom reticle events
void OnReticleEnter()
{
Debug.Log("Entering over " + this.name);
}
void OnReticleExit()
{
Debug.Log("Exiting over "+this.name);
}
void OnReticleHover()
{
Debug.Log("Hovering over "+this.name);
}
}
Related
So I am trying to make a hitscan laser weapon, from what I seen the weapon it self seems to be working. But I don't know how to make the ray visiable, I tried understanding line renderer but frankly I have no idea what I'm doing. Any tips?(This is the raycast code)
using System.Collections.Generic;
using UnityEngine;
public class Weapon : MonoBehaviour
{
private float damage = 10;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown("k"))
{
Shoot();
}
}
void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, Mathf.Infinity))
{
Health target = hit.collider.GetComponent<Health>();
if (target != null)
{
target.TakeDamage(damage);
}
}
}
}```
Maybe you could instantiate a laser sprite heading in the direction of the raycast going really fast
In the game I'm developing, the player moves left and right avoiding obstacles that fall from above, but when the player reaches the left or right limit, a collision bug may occur and he simply leaves the screen. I'm using the rigidbody.velocity and the trigger to check for collision but even so, there are times when it manages to cross the wall. Here the script.(And I'm not using FixedUpdate because it's not responding well when I tap the screen.)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ball : MonoBehaviour
{
public bool isRight;
public float speed;
public Transform pointR;
public Transform pointL;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if(isRight)
{
rb.velocity = new Vector2(speed, 0);
}
else
{
rb.velocity = new Vector2(-speed, 0);
}
if(Input.GetMouseButtonDown(0))
{
isRight = !isRight;
}
}
void OnTriggerEnter2D(Collider2D collider)
{
if(collider.CompareTag("ColisorEs"))
{
isRight = !isRight;
}
if(collider.CompareTag("colisorR"))
{
isRight = !isRight;
}
}
}
Rigidbody changes should be handled in the FixedUpdate methode. It's better for Unitys Physics.
You can leave your Input.GetMouseButtonDown in Update.
and thank you for looking at this in advance.
I have yet another problem that i need to solve and it goes like this:
I have a list of objects that i select with a raycast, and i would like to teleport them to a specific location in the scene. Like for example i have selected a cube and a sphere and they are added to my list called playersTagged.
How can i get the objects in my list to that specific location when OnCollisionEnter with my player that has the tag "Tagger"?
My code looks like this:
PlayerTagged Class
using System.Collections.Generic;
using UnityEngine;
public class PlayerTagged : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera fpsCam;
public List<GameObject> playersTagged;
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null && target.isHit == false)
{
target.takeDamage(damage);
if(hit.collider.tag == "Taggable")
playersTagged.Add(hit.collider.gameObject);
target.isHit = true;
}
}
}
}
Teleport class:
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player;
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
}
}
}
You need to have the PlayerTagged reference in your Teleport component. If both objects will always exist in your scene, only create a public field in your Teleport and drag and drop your PlayerTagged ref, otherwise you will need to fill this ref by code using some "find" approach, for example, GameObject.FindObjectWithTag().
You can also make an event that trigger when the object that entered the OnTriggerEnter is valid (I mean, when your tag condition pass) and then make sure that PlayerTagged is being registered as listener to this event.
First one is easier to setup, but if you plan to make unique things with this OnTriggerEnter as playing sounds, changing data or something like that, the second one is a better approach.
EDIT: I'll try to insert some code, let me know if you still having problems on getting the idea
"If both objects will always exist in your scene..."
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player; // I didn't saw that you already have an ref here, my bad, so you only need to access the fields
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
var list = player.playersTagged; // this is how you will access your list
// Do some stuff with your list
}
}
}
Ignore the rest, it will only complicate things
EDIT 2: Making the teleport happen in player, and teleport every object
using System.Collections.Generic;
using UnityEngine;
public class PlayerTagged : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera fpsCam;
public List<GameObject> playersTagged;
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
// Option 1:
private void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Teleport Tag")
{
var teleport = col.gameObject.GetComponent<Teleport>();
TeleportObjectsTo(teleport.teleportTarget.position);
}
}
void Shoot()
{
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null && target.isHit == false)
{
target.takeDamage(damage);
if(hit.collider.tag == "Taggable")
playersTagged.Add(hit.collider.gameObject);
target.isHit = true;
}
}
}
public void TeleportObjectsTo(Vector3 targetPosition)
{
foreach(taggedObjects in playersTagged)
{
taggedObjects.transform.position = targetPosition;
}
}
}
You can also make the teleport happen on teleport script:
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Transform teleportTarget;
public PlayerTagged player; // I didn't saw that you already have an ref here, my bad, so you only need to access the fields
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Tagger")
{
Debug.Log("You hit the can");
// Option 2:
player.TeleportObjectsTo(teleportTarget);
// Option 3: Or you can iterate here instead of make use of the API
foreach(var taggedObjects in player.playersTagged)
{
taggedObjects.transform.position = targetPosition;
}
}
}
}
Chose one option, and delete/comment others
--N
How do i localize other GameObject position
and Move to it (like teleport to that object) how can i do it?
BotController.Player
it's object what i want to get position of it and move to it (teleport)
i work on game hack
In case you already have reference to the target object you can just use this.position = BotController.Player.position anywhere in the object you wanna teleport.
public class EasyTeleporter : MonoBehavior
{
...
public void SomeFunction()
{
position = BotController.Player.position
}
}
If you are creating first person game and want to achieve something like teleporter to any object you should use raycasting for that.
For example you can take Unity default asset FirstPersonCharacter (available on asset store or you can add it when starting a new project) and add the following script to the FirstPersonCharacter gameobject (wich is child of FPSController prefab):
using UnityEngine;
using System.Collections;
public class PlayerTeleporter : MonoBehaviour
{
bool shooting = false;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
shooting = true;
}
}
void FixedUpdate()
{
if (shooting)
{
shooting = false;
RaycastHit hit;
// you are casting a ray in front of your camera wich hits the first collider in its path
if (Physics.Raycast(transform.position, transform.forward, out hit, 100f))
{
// normally you shouldn't teleport directly into the trget object
transform.position = hit.transform.position;
}
}
}
}
Generally you should clarify you question. What game you are creating, what are the target and object of teleportation and how do you wanna trigger that.
I making simple runner game.
I want do have some block over which player which jump.
I make a prefab and quad.
Attached Spawn script:
using UnityEngine;
using System.Collections;
public class SpawnScript : MonoBehaviour {
public GameObject[] obj;
public float spawnMin = 1f;
public float spawnMax = 1f;
// Use this for initialization
void Start ()
{
Spawn();
}
void Spawn()
{
Instantiate(obj[Random.Range(0, obj.GetLength(0))], transform.position, Quaternion.identity);
Invoke("Spawn", Random.Range(spawnMin, spawnMax));
}
}
Also I attached Destroyer script:
using UnityEngine;
using System.Collections;
public class DestroyerScript : MonoBehaviour {
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Application.LoadLevel(1);
return;
}
if (other.gameObject.transform.parent)
{
Destroy(other.gameObject.transform.parent.gameObject);
}
else
{
Destroy(other.gameObject);
}
}
}
But when player enter this object nothing happens.
Screen of my Quad:
Where is my mistake?
You use OnTriggerEnter2D. If your collider not ticked isTrigger field, you can use OnCollisionEnter2D.
And also if your object has Normal (3D) collider you need to use 3D versions of them.
OnTriggerEnter or OnCollisionEnter.
And also you should read this.
UPDATE
After discussion and looking your project problem is your character doesnt hit the destroyer object's collider. It moves with your main camera. (Destroyer object is child object of camera). Because of that when you take your destroyer from camera's child object it works.
Any child object in the heirarchy inherits it's parents movement. So if the collider is on a child object of the camera, it will move when the camera moves.