Is there anyway that I can do ray casting with tags? As in, I have a raycasting and if you are bla bla from an object with “zombie” tag, then avoid etc etc. This would be used for having multiple enemies and an object avoiding each one. Because I don’t want to have to use a transform method and ask for distances between each zombie. It would be more simple to just raycast and ask where each zombie is, then do the rest of my scripting for the AI.
There’s no way to cast against tags exclusively. The best way to do it is to cast against a particular layer and then filter the results by their tags, like so:
RaycastHit[] hitArray;
LayerMask layerMask;
layerMask = 1 << LayerMask.NameToLayer("Layer Name");
hitArray = Physics.RaycastAll(ray, dist, layerMask);
foreach (RaycastHit i in hitArray)
{
if (i.transform.gameObject.tag == "Player") {
// do something
}
}
Is this javascript because when I tried using this I just got crap loads of errors.
Sorry, C#. Search the ScriptReference for RaycastAll and you’ll see JS examples.
So the Shader.Find(“bla”), is the “bla” the tag?
function Update () {
var hits : RaycastHit[];
hits = Physics.RaycastAll (transform.position, transform.forward, 100.0);
// Change the material of all hit colliders
// to use a transparent Shader
for (var i = 0;i < hits.Length; i++) {
var hit : RaycastHit = hits[i];
var renderer = hit.collider.renderer;
if (renderer) {
renderer.material.shader = [b][color=red]Shader.Find("Transparent/Diffuse");[/color][/b]
renderer.material.color.a = 0.3;
}
}
}
No. The ScriptReference is really handy here: Shader.Find()
Tags are properties of GameObjects: GameObject.tag
As shown in my original example, you can filter by tag like so:
if (hit.transform.gameObject.tag == "Player") {
// do something
}
What you’re doing here is taking the Raycast hit result, then you’re accessing it’s transform, then you’re accessing that transform’s gameObject, and then you’re accessing that gameObject’s tag. It’s like moving up a tree.
To know how to climb the tree, you gotta learn what properties RaycastHit has: RaycastHit
So from looking at your C script I am thinking now I just replace the red area with…
function Update () {
var hits : RaycastHit[];
hits = Physics.RaycastAll (transform.position, transform.forward, 100.0);
// Change the material of all hit colliders
// to use a transparent Shader
for (var i = 0;i < hits.Length; i++) {
[color=red]var hit : RaycastHit = hits[i];
var renderer = hit.collider.renderer;
if (renderer) {
renderer.material.shader = Shader.Find("Transparent/Diffuse");
renderer.material.color.a = 0.3;
}[/color]
}
}
to make
function Update () {
var hits : RaycastHit[];
hits = Physics.RaycastAll (transform.position, transform.forward, 100.0);
// Change the material of all hit colliders
// to use a transparent Shader
for (var i = 0;i < hits.Length; i++) {
[color=green] if (hit.transform.gameObject.tag == "Player") {
// do something
}[/color]
}
}
Almost! Because you’re not using a ForEach loop, but a regular For loop, you’ll have to access the hits[ ] array a bit differently:
function Update () {
var hits : RaycastHit[];
hits = Physics.RaycastAll (transform.position, transform.forward, 100.0);
for (var i = 0;i < hits.Length; i++) {
if ([B][COLOR="red"]hits[i][/COLOR][/B].transform.gameObject.tag == "Player") {
// do something
}
}
}
In my original example, the ForEach loop was accessing it’s way through the hits array and spitting out each item as the “hit” variable. But that’s not the case with a normal For loop. You have to use “i” to access the proper array index.
Ok so atm I got no errors, I will start testing it soon, then Ill report back if it worked or not
Hey so this is my current code:
var speed2 = 24;
var radiusBot : float =20.0f;
function Update () {
var hits : Collider[];
hits = Physics.OverlapSphere (transform.position, radiusBot);
for (var i = 0;i < hits.Length; i++) {
if (hits[i].transform.gameObject.tag == "zombie") {
print("something");
if(!Physics.Raycast(transform.position, transform.forward, 5)) {
transform.Translate(Vector3.forward * Time.smoothDeltaTime * speed2);
}else{
print("action here");
}
}
}
}
What I want to do now is ask which of the zombies is closest within my sphere of raycasting, and then ask what that closest zombie’s position is. How would I go about doing this?
var speed2 = 24;
var radiusBot : float =20.0f;
var closestTransform : Transform=null;
function Update () {
var hits : Collider[];
hits = Physics.OverlapSphere (transform.position, radiusBot);
var closestDistance : float = radiusBot;
for (var i = 0;i < hits.Length; i++) {
if (hits[i].transform.gameObject.tag == "zombie") {
print("something");
var distance : float = Vector3.Distance (transform.position, hits[i].transform.position);
if (distance < closestDistance) {
closestDistance = distance;
closestTransform = hit[i].transform;
}
if(!Physics.Raycast(transform.position, transform.forward, 5)) {
transform.Translate(Vector3.forward * Time.smoothDeltaTime * speed2);
} else {
print("action here");
}
}
}
}
Is there anyway after taking the closest zombie’s position, determining if it is behind, in front of, to the side (right or left). Of the object the script is attached to.
Alternately, if you’re running into issues of your Raycast hitting stuff it shouldn’t but you don’t want to use layers for some reason, you could do something like this:
//Reserve a slot for the closest zombie
var closestZombie:GameObject;
//Save the distance of the last zombie which was saved
var closestZombieDistance:float = 0;
//Find all the objects with that tag
var colliderTests:GameObject[] = GameObject.FindGameObjectsWithTag("myTag")
//Sweep through the array
for(var GO in colliderTests){
//If the game object has a collider
if(GO.collider){
//Test that collider for the raycast
var raycastHit:RaycastHit = GO.collider.Raycast(ray, dist);
if(raycastHit){
//We've hit a zombie!
if(!closestZombie || raycastHit.distance < closestZombieDistance){
//If this is the first zombie found,
// or it's closer than the one we've saved
// save the zombie
closestZombie = GO;
closestZombieDistance = raycastHit.distance;
}
}
}
}
//If we've found a zombie....
if(closestZombie){
//Brain the zombie!
}
As for your other question about determining where the zombie is in relation to the observer, here’s a solution which might work:
//This needs to be set up through other code
var zombie:Transform;
//Find the direction toward the zombie
var vectorToZombie:Vector3 = zombie.position - transform.position;
//Find the dot product of my forward axis to the direction to the zombie
// The dot product compares two vectors and returns a float telling how they compare.
// 1.0 == Vectors are equal
// 0.0 == Vectors are perpendicular
// -1.0 == Vectors are opposite
var dotToZombie:float = Vector3.Dot(transform.forward, vectorToZombie);
if(0.5F < dotToZombie){
//Zombie is in front of me
}else if(-0.5F < dotToZombie){
//Zombie is to my side
}else{
//Zombie is behind me
}
regarding your ladder post, you have three directions, from, behind, and side. How would you know which side it is on?