- Home /
Visible Bullet Tracers and Lasers Clarification
I know this question is probably very redundant, but please hear me out.
So I'm working on space adventure game with heavy combat elements with intentions of expanding it with role playing elements as I go. I'm a graphic designer with strong knowledge on programming with Javascript from my time spent in web design and I have been learning the ropes of Unity. Introductions said and done, here is my question:
I'm trying to understand some of the pros and cons, along with the finer details of methods used for lasers, bullets, and so on.
The first method I see most commonly is using a particle system with raycast. I have yet to spend a lot of time using raycast, but from what I understand, it detects a collision with an object and if the fire button is pressed, it applies damage to the object colliding with the raycast. My main problem with this is that the damage is instant and you can't dodge the projectiles, not to mention running into the particles themselves does nothing.
The second method is to use a particle system with a particle collider, but with this you can't detect where the particle is colliding for generating impact effects (they impact in the center of the object they're colliding with, not the point of collision). I also noticed that the reference manual says that particle collision uses a lot of overhead, but the particle system only uses one draw call(?).
The one I see second most commonly is an object with a trail renderer. My question is what kind of object do you tie it to? An invisible mesh? An empty game object? Does it have a rigid body? My main problems I've seen with this is draw calls and objects skipping past collisions. On the plus side however, speeds could be easily adjusted and effects (sparks, explosions) would be easy upon destruction and lights could be added.
The last one I've seen is a line renderer which seems to use similar methods to method #3.
So finally, here is what I am looking for specifically:
Lasers/bullets that have a tracer and are clearly visible.
Adjustable speeds and can be dodged (if slow enough).
Have an impact effect of some kind on point of impact (sparks, explosion, etc).
Can be given some kind of small, randomized angle to make them slightly imperfect (if I choose).
A lot of these projectiles will be on screen (huge capitol ship battles, turrets, etc)
A PLUS: If it's not too heavy on overhead, emits light.
Any help will be GREATLY appreciated. I'm building it for computer, so I'm not trying to cram this onto an iPhone, though I'd still like to try and keep it optimized.
Answer by syclamoth · Nov 08, 2011 at 07:37 AM
Well, this is a bit of a huge question. I'll try to address it point by point!
Assuming you have a single script which you set up in the inspector for different kinds of projectiles (despite how horrendously unrealistic slow lasers are, but that doesn't matter), your script needs to have the following-
Starting Velocity (determined by the direction of the gun * bullet speed, modified by a random value)
Impact particles (just a one-shot particle effect, instantiated on impact)
Renderer (including a material)
Accurate collision detection (as in, better than what rigidbody physics can provide for you)
Now, it's kind of a 2-stage thing, since both the gun and the projectile play their own parts in this. You should be able to set up the gun so that it can shoot any kind of projectile which meets certain criteria, and set up the projectile so that it meets some common interface or standard. Exactly how you do this is up to you- you have quite a few different options.
The gun needs to know a few things-
What direction it is facing (easiest to just use the Transform for that)
How accurate it is (a number between 0 and 1, where 0 is shooting in a random direction and 1 is always shooting straight ahead)
How fast the projectile is moving when it is spawned
Given this information, I would then do something like this to acutally do the shot-
void ShootBullet()
{
Vector3 shootDirection = Vector3.Slerp(Random.insideUnitSphere, transform.forward, accuracy);
Vector3 shootVector = shootDirection * shotPower;
GameObject bullet = (GameObject)Instantiate(bulletPrefab, transform.position, transform.rotation);
bullet.SendMessage("SetVelocity", shootVector);
}
This will instantiate a prefab, and then send a message to the newly-created object telling it what direction to move in. Now, this message can be implemented any way you like- so you could have a rigidbody-controlled projectile, in which you would just set its velocity to the shootVector, or you could be using a transform.Translate-controlled one, which case you would do something different.
Now, the collision detection thing is another thing you need to look out for- to avoid the 'bullet through paper' problem, you need to do more than just rely on Rigidbody physics to manage everything for you. The way I do this, is using Physics.Linecast between the object's previous location, and its current location.
void CheckCollisions()
{
RaycastHit hit;
if(Physics.Linecast(previousPosition, transform.position, out hit))
{
// we hit something, get information back out of it
// now we can apply force, deal damage, spawn particle effects etc.
}
previousPosition = transform.position;
}
As for the optimisation problem, I wouldn't recommend adding lights to lots and lots of projectiles, but you can do that on key ones to draw the eye to them. Depending on the shader, you can do self-illuminated glowing textures, or particles- but in the end it really just comes down to testing. See how many bullets you can manage!
Thanks for the quick reply man, I'm definitely grateful! I've been pulling my hair out trying to find a straight answer to this.
I'm still getting into working with physics casters, but I'm sure I can find some more tutorials for that. As for the projectiles and performance, instantiating lots of these projectile game objects and then destroying them after, say... 10 seconds, won't gum up the frame rate or performance correct? Or will this approach eventually add up and kill my frame rate in the end? It also sounds as if I could skip having a rigid body all together if the collision is being detected by linecast.
Also, do each of these projectile objects need to have a visible mesh of some kind in them? Or can an empty game object be assigned all of the components necessary? Granted a billboard plane likely counts as a mesh even though it only has 1 face, if I go that route.
Somewhat related/unrelated question: Would it also be wise to pool the particles effects and move/call them to position of the collision rather than just instantiate new objects each time?
I apologize if these questions are overly trivial.
No, there's absolutely nothing to say the bullets have to have meshes on them (or in fact be visible at all, but you want your game to not be unendingly frustrating to play). Your idea with pooling the particle effects is a good one- you can do very clever things with moving particle effects around and emitting particles at specific points. I've never gone down that route personally, but I can see it working quite nicely. You can assemble gameObjects at runtime, if you feel like it, using AddComponent- prefabs only really exist for convenience.
Don't apologise for your questions - for one thing, they're far less trivial than some of the questions we get here, and for another, you seem to be aware of the fact that see$$anonymous$$gly simple concepts can have complex implementations, which is something a lot of people fundamentally don't seem to understand...