how to use Raycast NGUI in RTS Game? - unity3d

I am working on the 2D Isometric RTS project.
It's like They are Billions or Starcraft.
But while working on the map-editor, RayCast faced an unbreakable problem with NGUI.
Although you must create the ground when you click the mouse, UICamera.hoveredObject will continue to return UIRoot
Scenes returning UIRoot
private void CreateTileOnMousePos()
{
Debug.Log(UICamera.hoveredObject);
if (UICamera.hoveredObject == null)
{
RaycastHit2D hit;
if (hit = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition)))//, grid.unwalkableMask))
{
Node node = grid.NodeFromWorldPoint(hit.point);
Vector3Int pos = tilemaps[0].WorldToCell(node.worldPosition);// + tilemaps[0].tileAnchor);
node.enviormentTile = EnviormentTile.Gress;
tilemaps[0].SetTile(pos, tilePrefabs[0]);
}
}
}
If UIRoot's SetActive is off, of course it works.
Select another tile or save/load map information through UIButton.
I want to use these NGUI to implement the interface of real game
I don't know if the transition is stupid because it's my first time working on it.
I would appreciate it if you could tell me how to do what I intended without turning off UIRoot SetActive
===========================================================================
I don't know how to use GraphicRayCast due to lack of skills, but first I solved it by that method.
if (UICamera.Raycast(Input.mousePosition) == true)
{
Debug.Log("UICamera.Raycast ture");
}
else
{
RaycastHit2D hit;
if (hit = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition)))//, grid.unwalkableMask))
{
Node node = grid.NodeFromWorldPoint(hit.point);
Vector3Int pos = tilemaps[0].WorldToCell(node.worldPosition);// + tilemaps[0].tileAnchor);
node.enviormentTile = EnviormentTile.Gress;
tilemaps[0].SetTile(pos, tilePrefabs[0]);
}
}

Related

Force occasionally being applied twice with OnCollisionEnter

I am creating a first person rocket jumping game, with the premise of shooting a rocket launcher at the players feet to move around.
I am having problems with my OnCollisionEnter function which stores all colliders in a radius and applies explosion force to them. When the player is completely on top of the explosion, force is being applied twice. Here is the code:
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Player")
{
}
else
{
GetComponent<AudioSource>().Stop();
Instantiate(explosionPrefab, transform.position, transform.rotation);
Vector3 explosionPos = transform.position;
//Use overlapshere to check for nearby colliders
Collider[] collidersToDestroy = Physics.OverlapSphere(explosionPos, radius);
foreach (Collider hit in collidersToDestroy)
{
//searches for what needs to be destroyed before applying force, this is for destructable objects
Destructible dest = hit.GetComponent<Destructible>();
if (dest != null)
{
dest.DestroyWall();
}
ExplosiveBarrel barrel = hit.GetComponent<ExplosiveBarrel>();
if (barrel != null)
{
barrel.BarrelExplode();
}
}
Collider[] collidersToMove = Physics.OverlapSphere(explosionPos, radius);
foreach (Collider hit in collidersToMove)
{
Rigidbody rb = hit.GetComponent<Rigidbody>();
//Add force to nearby rigidbodies
if (rb != null)
{
rb.AddExplosionForce(power * 5, explosionPos, radius, 3.0F);
if (hit.gameObject.tag == "Player")
{
//if player is hit
UnityEngine.Debug.Log("Hit");
}
}
Destroy(gameObject);
}
}
}
I can tell the force is being applied twice to the player by using UnityEngine.Debug.Log("Hit"); , which appears twice in the console. Furthermore, I am pretty sure this is happening on the same frame, as putting Destroy(gameObject); within the if (player hit) statement yields the same results.
This only occurs when the player is right next to the explosion, if the player is a small distance away the force is only applied once. I would very much like to solve this problem and have the force only applied once.
All help is greatly appreciated, thank you in advance.
I solved it!
OnCollisionEnter was being called twice because I had two colliders perfectly stacked on one another, so the projectile was hitting the 2 colliders on the same time step.

Unity and Oculus Raycast from Motion Controller Only working at Guardian Border

I have coded up a simple raycast script that is attached to the hand of an Oculus Motion Controller. The idea is - the controller acts like a vacuum, it sucks up the prefabbed objects called "Eosinophil2(Clone)".
On a few tests outside of the motion controller this works.
The trouble I am experiencing is when I place the Raycast script into the motion controller. It only appear to work as anticipated when I am beside the Guardian Border.
I have turned on and off the border to see if that solved anything but it did not.
I've checked that the line raycast line goes in the right direction - and it is.
Any ideas?
void FixedUpdate()
{
// OVRInput.SetControllerVibration(.3f, 0.3f, OVRInput.Controller.RTouch);
var up = transform.TransformDirection(Vector3.forward);
//note the use of var as the type. This is because in c# you
// can have lamda functions which open up the use of untyped variables
//these variables can only live INSIDE a function.
RaycastHit hit;
Debug.DrawRay(transform.position, up * 20, Color.green,1);
if (Physics.Raycast(transform.position, up, out hit, 20))
{
if (hit.collider.gameObject.name == "Eosinophil2(Clone)")
{
OVRInput.SetControllerVibration(.3f, 0.3f, OVRInput.Controller.RTouch);
hit.collider.gameObject.transform.position = Vector3.MoveTowards(hit.collider.gameObject.transform.position, transform.position, 20 * Time.deltaTime);
}
else
{
//OVRInput.SetControllerVibration(0, 0, OVRInput.Controller.RTouch);
}
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.transform.name == "Eosinophil2(Clone)")
{
this.gameObject.GetComponent<AudioSource>().Play(0);
Debug.Log("works");
Destroy(other.gameObject);
Debug.Log("HIT ONE!");
hitRate++;
}
}`enter code here`
Moral of the story - build your scene from scratch.
Use the OVRCameraRig prefab in said build scene.
Using prebuilt scenes from Oculus can be detrimental to ones health, time and code.
I hope this helps someone someday.

GameObject Follow cursor yet also follows enemies?

I'm making a simple character that follows the player's cursor. What I also want is for when the game object "enemy" appears the character then goes to that location to alert the player. Once the enemy is gone the character continues to follow the cursor like normal. Is there a reason why my script won't work. How else can I paraphrase it?
public class FollowCursor : MonoBehaviour
{
void Update ()
{
//transform.position = Camera.main.ScreenToWorldPoint( new Vector3(Input.mousePosition.x,Input.mousePosition.y,8.75f));
if (gameObject.FindWithTag == "Enemy")
{
GameObject.FindWithTag("Enemy").transform.position
}
if (gameObject.FindWithTag != "Enemy")
{
transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,8.75f));
}
}
}
You are not using FindWithTag correctly, as it is a method that takes a string as parameter you need to use it like this:
GameObject.FindwithTag("Something") as stated in the Unity scripting API
Now to apply this to your code you would need to do the following to set your players position based on wether or not an enemy is found (assuming this script is on your actual player object):
if(GameObject.FindWithTag("Enemy"))
{
//If an enemy is found with the tag "Enemy", set the position of the object this script is attatched to to be the same as that of the found GameObject.
transform.position = GameObject.FindWithTag("Enemy").transform.position;
}
else
{
//when no enemy with the tag "Enemy" is found, set this GameObject its position to the the same as that of the cursor
transform.position = Camera.main.ScreenToWorldPoint( new Vector3(Input.mousePosition.x,Input.mousePosition.y,8.75f));
}
However this code will just snap your player instantly to the position of the found Enemy. If this is not the desired behaviour you could use a function like Vector3.MoveTowards instead to make the player move to it gradually.
This code also has room for optimisation as searching for a GameObject every update frame is not the ideal solution. But for now it should work.
I'm going to code coding all the function for you, I'm not pretty sure about the beavihour of your code, I understand a gameobject will be attached to the mouse position, so not really following....
Vector3 targetPosition;
public float step = 0.01f;
void Update()
{
//if there is any enemy "near"/close
//targetPosition = enemy.position;
//else
//targetPosition = MouseInput;
transform.position = Vector3.MoveTowards(transform.position, targetPosition , step);
}
For the f you can use a SphereCast and from the enemies returned get the closest one.

onCollsionEnter specifying objects?

I'm currently making a infinite runner type game for a class project and I need some help with collisions.
The game is set up as a 2d platform where a character is running (or made to look like they're running with a scrolling texture) through an infinite tunnel. The player has to avoid obstacles similar to Flappy Bird using jumps. The script I'm using at the moment is setup so that when the player collides with obstacles the game will reload.
The issue:
The issue is that the code I've used applies to all collisions so when the player hits the ground platform the game reloads.
What I want to happen:
I want the character to be able to run on a platform and die when he hits the a specific obstacle.
So I'm think I need to specify a GameObject to collide with?
This is my current code:
// Update is called once per frame
void Update ()
{
// Jump
if (Input.GetKeyUp("space"))
{
rigidbody2D.velocity = Vector2.zero;
rigidbody2D.AddForce(jumpForce);
}
// Die by being off screen
Vector2 screenPosition = Camera.main.WorldToScreenPoint(transform.position);
if (screenPosition.y > Screen.height || screenPosition.y < 0)
{
Die();
}
}
// Die by collision
void OnCollisionEnter2D(Collision2D other)
{
Die();
}
void Die()
{
Application.LoadLevel(Application.loadedLevel);
}
}
Use tags. For example, use a terrain tag for the ground. If the object tag is terrain, then don't die.
Here is a simple example:
void OnCollisionEnter2D(Collision2D other)
{
if (other.collider.tag == "Terrain")
{
Debug.Log("Don't die!");
}
else
{
Debug.Log("Die!");
}
}

Only select the first sprite in a pile of sprites (Unity3D 2D-game)

I have a number of sprites on top of each-other on the game board. When i use the mouse and select the sprite on top, all sprites under the mouse position is selected. My question is how to only select the sprite that I click on and not catch the ones below?
Here is the code i am using for my tests, attached to the sprites:
function Update () {
if(Input.GetMouseButtonDown(0)) {
var theActualMousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
// print("ALL MousePosition: " + theActualMousePosition);
if(collider2D.OverlapPoint(theActualMousePosition)) {
// print("HIT theActualMousePosition: " + theActualMousePosition);
print(collider2D.gameObject.tag);
}
}
}
The results you are getting are completely expected as your code is placed on the GameObjects, what you should do is to push your script out of those objects or use another function than OverlapPoint (because overlap point does not check for collision it simply checks if you are in the bounds of an object, which means it is valid for all object)
Some ideas :
Using OnMouseDown should provide you with an event only for the first collider encountered
Using A raycast from the camera : Camera.ScreenPointToRay should be able to be used for a raycast and then to check only the first collider encountered
Using Layers depending on layer collision Order.
EDIT :
Or you could also cast the ray the other way around :
function Update () {
if(Input.GetMouseButtonDown(0)) {
var theActualMousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 direction = (transform.Position-theActualMousePosition).normalized;
Ray ray = Ray(transform.Position,direction)
if(Physics.Raycast(ray) == null) {
//Then there is nothing between the object and the camera then the object is the first one
print(collider2D.gameObject.tag);
}
}
}