- Home /
make shadow interactive?
I'm making a puzzle game in which the player character is a shadow on a wall and there are multiple 3d objects in the room which shadows are cast to the wall and the player can move and rotate those 3d objects (bring them close to a light source and the shadow on the wall will become bigger), the player character can't interact with 3d objects but can interact with their shadows like climb on shadow of a table, now the question is how can I make my shadow interactive.
Note: I'm not asking for a script, I just need a starting point.
Is the perspective fixed or variable? If the perspective is fixed this could be easily accomplished by having invisible versions of the shadow casters that are placed along the wall and resized appropriately. If the perspective is not fixed you could track the area covered by the shadow and either write your own physics-like interactions when the shadows intersect or resize/reshape one or more invisible geometries to handle it for you.
the perspective is fixed but player can move the 3d objects to resize it's shadow. can you plz explain a little more how to write physics interaction? any source
If the perspective is fixed and you just move the objects to resize the shadow, it will be far easier to simply scale the invisible duplicate of that object. Is there a specific reason you don't want to do it that way?
Answer by Roger_0123 · Jun 07, 2020 at 01:33 PM
Really interesting, but I think you need to create your shadow as a GameObject, as I think Unity Lightning system does not handle shadow interactions. So you probably need to simulate them
shadow as a gameobject? how? I tried using render texture but was not looking good.
Answer by Eno-Khaon · Jun 07, 2020 at 07:57 PM
As a general rule, you can expect an object to cast its shadow directly away from a light at any given point. With this expectation in mind, as others have mentioned, the most important element to give the shadows "volume" is to give them appropriate colliders.
(To note, there is a confounding factor, because the camera's perspective can visually separate an object's shadow when spread between multiple receiving surfaces, but that's a problem best saved for later)
Since your character is fundamentally only a shadow, your gameplay is presumably 2-Dimensional, so what a collider "looks like" won't matter as long as that playfield isn't disrupted by it. Furthermore, this also likely means you'll need a pair of collision meshes per environmental GameObject, where one is its actual 3-D presence and the other is its shadow, only able to be interacted with by shadow characters.
Example: A simple table should have five cubic colliders, one for the body and one for each leg (Note the varied shapes of the shadows depending on subtle differences in light position)
You'll want to keep your colliders simple for this; they should all be low-polygon, convex colliders wherever possible. This is because you'll be firing raycasts from each vertex of the collider to your wall.
// NOTE: THIS IS *DEFINITELY* NOT ROBUST (or usable) AS-IS
// Point light/spot light solution
Plane wallPlane; // The current wall that the player is a shadow cast onto
// The current world coordinates of the vertices of the collider, obtainable in numerous ways
Vector3[] baseColliderVertices;
// The resulting world coordinates after Raycasting from a light source to a wall
// The vertex count is doubled for point/spot light viability
Vector3[] transformedVertices = new Vector3[baseColliderVertices.length * 2];
for(int i = 0; i < baseColliderVertices .length; i++)
{
float hitDistance;
Ray lightRay = new Ray(baseColliderVertices [i], baseColliderVertices [i] - light.position);
if(wallPlane.Raycast(lightRay, out hitDistance))
{
// the resulting coordinates (e.g. 8 for a cube) will define the
// total shape of the usable shadow surface
// Set the first transformed position to the hit point of the raycast
transformedVertices[i*2+0] = lightRay.origin + lightRay.direction * hitDistance;
// Match that position for the second
transformedVertices[i*2+1] = transformedVertices[i*2+0]
// add depth for a walkable surface attached to the wall
transformedVertices[i*2+0] += wallPlane.normal;
transformedVertices[i*2+1] -= wallPlane.normal;
}
}
// Now you can filter out any Raycasts that didn't make contact
// with the wall (i.e. every vertex may not have been
// between the light and the wall)
// You will also need to rebuild the collider at this point (point/spot
// light only, directional light can get away with scaling only) and
// test immediate collision changes to move any
// shadow characters out of unexpected collisions
This is definitely not a simple undertaking, and it becomes drastically more complex with higher collider polygon counts and more (and varied) playable surfaces. (For example, what I provided above only account for flat walls)
At any rate, hopefully, this will be enough to help you get started!
plz can you explain why the raycast is used I tried to understand it but can't
The Plane Raycasts in my example are basically used to deter$$anonymous$$e where the shadow's corners will be located.
Because a (point) light focused on a cube is able to cast shadows in a variety of shapes, you first need to deter$$anonymous$$e the boundaries of that shape. To do that, a series of Raycasts from each vertex away from the light source will give an approximate idea of the way the shadow would be cast on that surface. (And a Plane.Raycast() is much simpler to calculate than Physics.Raycast() where applicable)
thank you for your time. let me implement it, then I'll tell you if it worked
Your answer
Follow this Question
Related Questions
Best way to physics collision 1 Answer
Blob Shadow 3 Answers
Will other player see what I see? 1 Answer