I am using rigidbody.velocity, but is this the best method in terms of efficiency? What I am wondering is, what is the most cost effect method to move an object?
The most cost effective way is to “fake” the bullet.
Shoot a ray when fired, add sound effects, and a bullet mark. You would never see the bullet, but its more of an illusion, a lot of games do this to be more efficient, especially with machine guns. It would destroy your framerate to have 200 ridgidbodies at once.
The only ways I know of is with a ridgidbody, a ray, or a box collider with an animation. There may be other ways, but considering they aren’t widely used it probably wont be very efficient.
Here is a script I made for a pistol, you will have to heavily modify it to suit your needs though.
#pragma strict
private var m_TimerResetOffset = 0;
var endTime : float;
var textMesh1 : TextMesh;
var projectile : Rigidbody;
var c1 : Color = Color.yellow;
var c2 : Color = Color.red;
var objecthit : GUIText;
var lineRenderer : LineRenderer;
var gunparticles : GameObject;
var bulletHole : GameObject;
var target1 : GameObject;
var target2 : GameObject;
var cameras : GameObject;
var cameras1 : GameObject;
var maincamera : GameObject;
var maincamera1 : GameObject;
var instructions : GameObject;
var targetpracticemusic : GameObject;
var startmusic : GameObject;
//var newhighscore : GameObject;
var fifteensecondsleft : GameObject;
var onesecondsleft : GameObject;
var textMesh : TextMesh;
var newhighscore : TextMesh;
var score = 0;
var nextFireTime : float;
function Start() {
newhighscore.text = "High Score: " + PlayerPrefs.GetInt("High Score").ToString();
Screen.showCursor = false;
endTime = Time.time + 61;
//textMesh = GameObject.Find ("Timer").GetComponent(TextMesh);
textMesh1.text = "Time: 60";
lineRenderer = gameObject.AddComponent(LineRenderer);
lineRenderer.material = new Material (Shader.Find("Particles/Additive"));
lineRenderer.SetColors(c1, c2);
lineRenderer.SetWidth(0.2,0.2);
lineRenderer.SetVertexCount(2);
}
function Update () {
//var guiTime = Time.time;
var guiTime = Time.time - m_TimerResetOffset;
var timeLeft : int = endTime - guiTime;
if (timeLeft == 0 cameras.gameObject.active == false){
timeLeft = 0;
maincamera.gameObject.active = false;
maincamera1.gameObject.active = true;
maincamera1.animation.Play();
Invoke("Gamereset", 7.7);
if(score > PlayerPrefs.GetInt("High Score")){
PlayerPrefs.SetInt("High Score", score);
newhighscore.text = "New High Score!";
Invoke("changehighscoretext", 7.7);
}
}
//game over stuff, save if high score
//reset scene in 7.8 seconds, with .loadlevel or manually.
if (timeLeft == 15 target2.gameObject.active == true){
fifteensecondsleft.audio.Play();
}
if (timeLeft == 3 target2.gameObject.active == true){
onesecondsleft.audio.Play();
}
textMesh1.text = "Time: " + timeLeft.ToString();
textMesh.text = "Score: " + score;
var fwd = transform.TransformDirection (Vector3.forward);
var origin = transform.position;
var direction = transform.forward;
var endPoint = origin + direction * 100000;
var hit : RaycastHit;
lineRenderer.SetPosition(0, origin);
if(Input.GetMouseButtonDown(0) || (Input.GetMouseButtonDown(1)) || (Input.GetMouseButtonDown(2)) || (Input.GetKeyDown (KeyCode.Space))){
if ( Time.time >= nextFireTime ) {
audio.Play();
gunparticles.gameObject.active = true;
Invoke("turnoff", .4);
if (Physics.Raycast(transform.position, fwd, hit, 1000)) {
var hitRotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
// var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position, transform.rotation);
//instantiatedProjectile.velocity = (hit.point - instantiatedProjectile.transform.position).normalized * .1;
// instantiatedProjectile.rotation = Quaternion.LookRotation(instantiatedProjectile.velocity);
nextFireTime = Time.time + .387;
print ("There is something in front of the object!");
objecthit.text = "You Hit: " + hit.collider.name;
lineRenderer.SetPosition(1, hit.point);
Instantiate(bulletHole, hit.point, hitRotation);
if(hit.collider.gameObject.name == "med perfect") {
score += 7;
}
if(hit.collider.gameObject.name == "med big") {
score += 3;
}
if(hit.collider.gameObject.name == "med med") {
score += 5;
}
if(hit.collider.gameObject.name == "big perfect") {
score += 5;
}
if(hit.collider.gameObject.name == "big big") {
score += 1;
}
if(hit.collider.gameObject.name == "big med") {
score += 3;
}
if(hit.collider.gameObject.name == "small perfect") {
score += 15;
}
if(hit.collider.gameObject.name == "small big") {
score += 5;
}
if(hit.collider.gameObject.name == "small med") {
score += 7;
}
if(hit.collider.gameObject.name == "Target Practice") {
target1.gameObject.active = false;
target2.gameObject.active = true;
m_TimerResetOffset = Time.time;
cameras.gameObject.active = false;
cameras1.gameObject.active = false;
targetpracticemusic.audio.Play();
FadeOutSound();
}
if(hit.collider.gameObject.name == "Instructions") {
cameras.gameObject.active = false;
cameras1.gameObject.active = false;
if (instructions.gameObject.active == false){
instructions.gameObject.active = true;
}
}
if(hit.collider.gameObject.name == "Quit") {
Application.Quit();
}
}
}
}
}
function turnoff () {
gunparticles.gameObject.active = false;
}
var menuMusic:GameObject;
function FadeOutSound(){
if (!menuMusic){
// Get menuMusic if not already defined in Inspector
menuMusic = GameObject.Find("MenuMusic");
}
if (menuMusic) {
// wait 4 seconds then fades for 4.5s
yield WaitForSeconds (1);
for (var i = 0.027; i > 0; i-=.005){
menuMusic.audio.volume = i * .9;
yield new WaitForSeconds (.5);
print ("Fading...");
}
menuMusic.audio.volume = 0;
}
}
function Gamereset (){
target1.gameObject.active = true;
target2.gameObject.active = false;
maincamera.gameObject.active = true;
maincamera1.gameObject.active = false;
score = 0;
menuMusic.audio.volume = 0.027;
targetpracticemusic.audio.Stop();
}
function changehighscoretext (){
newhighscore.text = "High Score: " + PlayerPrefs.GetInt("High Score").ToString();
}
Yes, what 3 suggested is called a “hitscan” bullet, and most FPS’s use that method for any guns that shoot fast projectiles, like pistols and rifles. You do a ray cast from the gun and see if it collides with anything and add the force (if you want physics) directly to whatever you hit at that point. You then either don’t draw the bullet at all (just a muzzle flash at the gun and a spark at the target) or you draw a bullet trail along the same ray cast that disappears after half a second or so.
You should only use actual moving bullets if the gun is shooting a slow projectile, like a rocket launcher or plasma bolt or something.
Awesome guys, never thought of that.
Thanks!
Edit:
How does one manage speed of the ray, or do we just assume that the contact is instant. :?
Also, what about gun fire, from a machine gun where an enemy is hit with bullet 1, 2,3… Meaning, I have not tested yet, but when a ray is sent, is it killed the instant it makes contact with a collider? Or is it more like a laser, constantly flowing until instructed not to.
Sorry for asking, but I am thinking for my machine gun, I might invoke repeat a function to fire ray, fire ray, fire ray etc. would that be the best way to go about handling a machine gun?
It’s instant. You can do a Raycast by calling Physics.Raycast() . Usually if a game has a trail for a hitscan bullet, it’s basically just a line of wind/smoke that’s drawn and then fades out, it doesn’t really have to move.
For a machine gun you can use a Coroutine and WaitForSeconds() to do the delay between bullets. Something like this:
while(Input.GetButton("Fire1")
{
FireBullet();
yield WaitForSeconds(0.5f);
}
Awesome again.
So to create a trail, what would you use? Where I am concerned is length. How would, whatever is used for the smoke trail, know, not to go beyond where the ray hits a collider?