- Home /
Using CheckSphere to affect another Game Object?
What we are trying to do is check the radius around character and have those GameObjects set to another material(for example, to simply change the color of the GameObject to blue).
Our game is set on a grid of tiles, 10 in each row, 10 rows (10x10). When it is the Player's turn to move, we want the tiles underneath him to be highlighted blue if they are within his moveRange(which is simply a variable we set). Originally, we sent out a RaycastAll, and it worked well to the left, right, forward, and backwards, but we couldn't get it working with diagonal movements.
Now we're trying to use a CheckSphere, but the problem is that we're not sure how to affect the GameObjects the Sphere is reaching.
Here is the original method, a RaycastAll
function Test ()
{
var layerMask = 1 << 10;
var hits : RaycastHit[];
hits = Physics.RaycastAll (transform.position, Vector3(0,0,1), moveRange, layerMask);
for ( var i = 0; i < hits.Length; i++)
{
var hit : RaycastHit = hits[i];
hit.collider.renderer.enabled = true;
hit.collider.gameObject.renderer.material = gridColor;
}
}
The layerMask was set to only collide with the tiles, so it didn't change anything but tiles.
Here is what we have so far with a CheckSphere
var layerMask = 1 << 10;
if ( Physics.CheckSphere(transform.position, moveRange, layerMask) )
{
}
In the original, we affected the GameObjects that the Ray hit by using a Raycasthit. We have no idea how to do so with a CheckSphere.
Any help is appreciated, or if anyone has a better method of achiving our goals that we be appreciated as well.
Answer by robertbu · Mar 05, 2013 at 02:19 AM
You can use SphereCastAll() or CapsuleCastAll():
RaycastHit[] hits = Physics.SphereCastAll(transform.position, radius, Vector3.forward, 0.001f);
When I last tried, it failed if the distance (last parameter) was 0.0.
We've tried using SphereCastAll, but it doesn't seem to work at all. Or we simply don't understand what's it doing. It doesn't send to be casting out a Sphere from the Player's position(transform.position)
Just to be absolutely sure, I tested the line of code above before I posted it. It worked fine. The first parameter should be the position of your player. The last needs to be non-zero (but can be small like I have it here). I'm not sure why it has to be non-zero other than in testing it would not return any hits if it was 0.0.
I don't understand. I'm going to post another comment with the code, and a screenshot showing what it's doing and maybe you can help explain to me the problem.
Answer by Tristsin · Mar 05, 2013 at 03:26 AM
function SphereTest ()
{
var gos : GameObject[];
gos = GameObject.FindGameObjectsWithTag("Tiles");
for ( var go : GameObject in gos)
{
var thisTrans = transform.position;
var goTrans = go.transform.position;
var hits : RaycastHit[];
var layerMask = 1 << 10;
hits = Physics.SphereCastAll(thisTrans, a, Vector3(1,0,1), 0.1);
for (var i = 0;i < hits.Length;i++)
{
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;
}
}
This is a reply to a poster. I didn't know how else to reply with code and a screenshot. The problem is, the "sphere" doesn't seem to be a sphere, and nothing I do makes it so. Maybe I'm just not understanding the concept, but to me, Casting a Sphere means casting a Sphere(circle) from the transform.position of my player(where this script is attached) and then returning the tiles it hits, and then rendering those transparent. It seems to be doing..... I don't know. I've tried every possible solution to make sense of it. I want to make a circle around my player's position, and any of the tile's collider that are within that sphere's range, I want it to highlight them blue.
In the Screenshot, my Player Character is the Cube that is off to itself. The Cubes in the middle are currently just Cubes, nothing more.
SphereCastAll() takes a sphere shape and pushes it through the scene on the vector specified for the distance specified, noting any colliders it hits along the way. Are you sure that thisTrans is the transform of the Player? What is the scale of your game (i.e. is the 0.1 you are using for distance perhaps a big number)?
Before I posted, I attached a script with the above line of code, outputting the number of colliders it found each frame. Then I tossed a bunch of game objects into the scene and moved the "player" around to see what they sensed.
I played with SphereCastAll() and you are right. Its behavior is not what is expected. I'm sorry for the bad advice. Is there any reason you are not simply doing a distance check? I tried it out with a array of cubes, and it worked fine:
GameObject[] argo = GameObject.FindGameObjectsWithTag("Tile");
for (int i = 0; i < argo.Length; i++) {
if ((argo[i].transform.position - transform.position).magnitude < 1.8)
argo[i].renderer.enabled = false;
If you really need the SphereCastAll() to work, you can use it in the way it was intended. Pick a position for the start point that is on the Y axis of the player but with the given radius will not touch the tiles. Then use Vector3.down for the direction and give it a distance high enough to push down through the tiles. Worked just fine in my tests.
I'll give this a try, thanks. There's no particular reason to use SphereCastAll, I was actually hoping to find a better way anyway.
Alright, that works fairly well.
The problem is, none of these seem to be what we want. We would like a way to pin-point which tiles will be highlighted. With yours, it works alright, but we truly have control over the movement(like for example, if we wanted to restrict the movement diagonally but not vertically or horizontal. We're also used a OverlaySphere, but it gives about the same results as that.
Also did this:
function SphereTest ()
{
var gos : GameObject[];
gos = GameObject.FindGameObjectsWithTag("Tiles");
for ( var go : GameObject in gos)
{
var curDistanceX = Vector3.Distance(Vector3(go.transform.position.x, 0 ,go.transform.position.z), (transform.position.x, 0, transform.position.z));
var curDistanceY = go.transform.position.y;
if ( curDistanceX <= moveRange )
{
go.renderer.material.color = Color.blue;
}
}
}
but, again it didn't truly give us control over it. We are stumped honestly. We've been working on it for over 8 hours straight with pretty much every solution we come up with being not just right.
$$anonymous$$ore examples:
$$anonymous$$ost of the solutions gave us something like this.
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[X],[X],[X],[ ],[ ],[ ],[ ]
[ ],[ ],[X],[X],[X],[X],[X],[ ],[ ],[ ]
[ ],[X],[X],[X],[X],[X],[X],[X],[ ],[ ]
[ ],[X],[X],[X],[X],[X],[X],[X],[ ],[ ]
[X],[X],[X],[X],[P],[X],[X],[X],[X],[ ]
When in reality we would want something like
[[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[ ],[X],[ ],[ ],[ ],[ ],[ ]
[ ],[ ],[ ],[X],[X],[X],[ ],[ ],[ ],[ ]
[ ],[ ],[X],[X],[X],[X],[X],[ ],[ ],[ ]
[ ],[X],[X],[X],[X],[X],[X],[X],[ ],[ ]
[X],[X],[X],[X],[P],[X],[X],[X],[X],[ ]
Where your max movement from the starting position would be 4 blocks away, hopefully this explains it well.
The diagram didn't come out lined up like in notepad, but hopefully you can make it out. Empty spaces are unmovable, spaces with X are movable, and P represents my Player Character