Physics.Raycast going through desired object

Hello,

I have a small problem that I can’t seem to figure out. Hopefully I can describe and summarize the problem well enough to answer any queries about the problem.

Scene Hierarchy:
Actor1 - Layer: Faction1 - 1x1x1 in scale

    • AggroTrigger - Layer: Faction1 - 10’ cubed
      Actor2 - Layer: Faction2 - 1x1x1 in scale
    • AggroTrigger - Layer: Faction2 - 10’ cubed
      Wall1 - Layer: Environment - 10x3x3 in scale
      Wall2 - Layer: Environment - 10x3x3 in scale

Scene Layout:
In the middle of the scene is Wall1 with Wall2 is parallel beside it. On one side is Actor1 and Actor2 is on the opposite side. All objects are on 0 z-axis.

Lame Text Visual:
1 = Actor1
2 = Actor2
| = wall

1 | | 2

Desired Effect:
Actor1 will move away from Actor2 if there is no line of sight. If Actor1 and Actor2 has a clear line of sight with one another, they will attack each other.

Problem:
At the start, Actor1 does what it is supposed to. With the walls in the way, there is no line of sight. However, when Actor1 goes outside the AggroTrigger, Actor1 and Actor2 for some reason see each other through the walls and start attacking each other.

Technical Setup:
OnTriggerEnter and OnTriggerExit are used on the AggroTrigger. When an enemy actor enters the trigger, it gets put into a list of enemies in range. When there is an enemy in range, a line of sight function is activated to see if the actor can see any of its targets. If it can’t see its target, do what it was doing. The line of sight function uses a Physics.Raycast with the same range as the AggroTrigger (AggroTrigger has a 20’ radius, the raycast is 20’ long).

Code Snippits:
I summarized, simplified, cleaned up, and commented the code as best as I could for easier viewing. The CheckLoS() function is where the Physics.Raycast part is at and is where I theorize where the issue lies.

// A script that when an object enters an aggro trigger, it puts the target into an array.
// Then it will use a Physics.Raycast to see if the target is in the line of sight.
// If the target is in line of sight, attack target.

var attackTarget : Transform; // the target the actor attacks
var aggroRange : int = 20; // how far away can the actor get aggro?  used in raycast
var aggroArray : Array = new Array(); // all targets in aggro range
var aggro : boolean = false; // is the actor attacking something?

function Update()
{
	// if the actor has aggro...
	if (aggro)
	{
		// move towards and attack target
	}
	// if the aggro list isn't empty and the actor doesn't have an aggro target...
	else if (aggroArray.length > 1  !aggro)
	{
		// check the line of sight
		CheckLoS();
	}
	// if no aggro...
	else
	{
		// move towards destination
	}
}

function OnTriggerEnter (hit : Collider)
{
	// layer 15 is the environment layer
	if (hit.gameObject.layer != gameObject.layer  hit.gameObject.layer != 15  hit.gameObject.layer != 16  hit.gameObject.name != "AggroRange")
	{
		// add target to aggro list
	}
}

function OnTriggerExit (hit : Collider)
{
	// layer 15 is the environment layer
	if (hit.gameObject.layer != gameObject.layer  hit.gameObject.layer != 15)
	{
		// remove target from aggro list
	}	
}

// a function that checks to see if the aggro object in range can be seen
function CheckLoS()
{	
	var targetDirection : Vector3;
	var hit : RaycastHit;
	
	// cycles through the aggroArray
	for (var i : int = 0; i < aggroArray.length; i++)
	{	
		// gets the direction of the target in the array
		targetDirection = gameObject.transform.TransformDirection(array_AggroObject[i].transform.position);
		targetDirection -= gameObject.transform.position;

		// casts a ray towards the direction of the target.  If it hits something...
		if (Physics.Raycast (transform.position, targetDirection, hit, aggroRange))
		{	
			// if the raycast hits an environment layer or something that has the same layer as the actor, check next array index 			
			// use transform.root because the actors have a child that is a trigger.  want to make sure i have the actor instead.
			if (hit.transform.root.gameObject.layer == 15 || hit.transform.root.gameObject.layer == gameObject.layer)
			{
				aggro = false;
			}			
			// if raycast hits something else, the actor has aggro, and exits the function
			else
			{
				aggro = true;
				attackTarget = aggroArray[i].gameObject.transform);
				return;
			}
		}
	}
}

The adding and subtracting, toggling of aggro, los, ect… that all works. It’s just the Physics.Raycast shooting through the wall and reaching something it isn’t supposed to is my problem. This code was virtually re-written so there may be small bugs, but that isn’t the point of this post.

Any info would be appreciated. Thanks in advance.
-S

I just had a glance at your description and code, so please forgive me if I am totally wrong. I don’t understand why you are using:

targetDirection = gameObject.transform.TransformDirection(array_AggroObject[i].transform.position);
targetDirection -= gameObject.transform.position;

and not

targetDirection = array_AggroObject[i].transform.position - gameObject.transform.position;

JUST IGNORE IF I AM WRONG!

Is the ray going through the wall??? Does the wall have a collider on it to hit and block??

Or make your aggro ctrigger smaller and your ray bigger… er I think…

@Dantus
I build prototypes before spending an absurd amount of time developing a full engine. This is currently a prototype so the code isn’t 100% clean. Thanks for pointing that out though :slight_smile: After prototyping, I revise everything once I get the general bugs fixed.

@All_American
The walls have the desired collider as when i put a print() in the code, the raycast prints the wall so that tells me the raycast sees the wall… at least until it moves out of the aggro range then it hits through both walls and registers the enemy target.

Thank you both for the reply. The topic is still open and I still require help.

-S

To be sure you are raycasting in the right direction…

Also, take a look at linecast… might be useful since youre using layers

@jlcnz
Thank you for the suggestion. I worked on testing it and trying different methods with Linecast but the problem still remains :frowning:

Issue is still unresolved. Has anyone else had this problem or have any ideas on how I may resolve this issue?

-S

Likely to be an error in your code or the code logic, to fix it you’ll need to use the debugger or use many print statements to know exactly what state variables are set and what actions are executed in the code. That information should help pin down the issue or at least rule out what its not.

Its hard to say what’s wrong since you’ve provided edited code, but I don’t see you resetting the aggro boolean when you enter/exit the triggers? From a quick glance of the code you have provided could that be part of the problem?

I do notice one thing that may be affecting it. Hard to know as I dont know how you have your objects setup, but in the trigger events, you dont access the layer of the root object, while in the raycast you do…

Im personally more of a fan of using tags to determine who is a target, but I guess it should work the same…

You may also want to check if the arrayLength > 0 rather than > 1. Maybe you have a reason for this…

One final thing, you should probably change the distance to a float. Passing it as an int may result in the use one of the other overloaded functions which treats it as a layermask.

@Noisecrime
Thank you for the reply. The edited part of the code works on the work of the array which all targets are placed in, array error checking, AI input, ect… The aggro reset is in a function I didn’t list called RemoveTargetfromArray. Simply put, if the aggro array is empty, aggro = false and go back to what you were doing.

I have used print statements… What I may end up doing is rewriting the entire code itself to see if I can think of another way around this problem.

-S

@jlcnz
Thank you for the reply. I am using layers because there are multiple factions in this game concept (may change later if this keeps breaking). I have gotten a few ideas since you posted about the use of float vs int due to possible overload so i converted the int to a float and changed the numbers from 20.0 in the inspector to 20.1. Got the same result. However, when I changed it to 15.5, it worked how it was intended. I then decided to test the extreme and turn the aggro range to 1000. Something odd happened. At ~20, the two targets aggro’d each other. After re-reading the code line by line, I didn’t see anything that assigned the aggro range. I think it may be a compile bug or something so I’m going to remake the project. I’ll let everyone know how the test result turned out.

-S