- Home /
Raycast Positioning
I have been programming for some time now (nearly a year) and im only now beginning to make my first full attempt at a full fps(movement, guns etc). I have been looking at some fps packages and youtube videos but still havent got a solid answer for raycasting. The question is where is the best place to put a raycast? is it from the camera to the centre of the screen(which i currently have)? or is it from the position of the end of the gun then forward? or is there away in which i can position it from the end of the gun and shoot towards the middle of the screen? for the first two options i have tryed the third i have not found away to do this. thanks in advance.
Answer by zmar0519 · Apr 24, 2011 at 12:16 PM
from what I understand, you are looking to use a raycasting method for your gun. you could use the main cameras position (camera.main.gameObject.transform.position
), or use a ScreenPointToRay
method. This can be found in the documentation for clicking and instantiating particles, but you just need to replace Input.MousePosition.x
and Input.MousePosition.y
with Screen.width/2
and Screen.height/2
. When I was doing an fps, I used the camera.main.gameObject.transform.position
method, and my script is listed below. Feel free to use it, or refrence it for tips. Hope it helps!!! :)
BTW: The utility functions at the bottom are not necessary for the gun, but they were for other scripts that I wrote. Also, some of the code I got from the guns script in the bootcamp demo, simply because it was beyond me.
//Adds a component Menu for the script //helps making it easy to find. @script AddComponentMenu("FPS / Weapons / Gun") //requires the audio source component @script RequireComponent (AudioSource) //the enumeration storing the FireType info enum FireType { RayCast, Projectile } //the enumeration storing the ShotType info enum ShotType { Semi_Auto, Full_Auto, } enum ry { left, forward, right, back } //The number of clips the gun has var Clips : int; //The size of the clips var clipSize : int; //the boolean unlimited. If checked true, the gun will fire endless bullets //good for power ups or testing var unlimited : boolean = false; //the boolean autoReload. if checked true, the gun will auto reload. //using this and a small clip will make a burst type gun var autoReload : boolean = true; //the range of the gun. type "Infinity" if you want it to be infinite. var gunRange : float; //the fire rate of the gun var fireRate : float; // the projectile prefab. this will only affect the gun if the fireType is set to Projectile var projectilePrefab : Rigidbody; //the shot power. once again, this will only affect the gun if the fireType is set to Projectile var projectileShotPower : float; //the damage each shot deals var Damage : int; //the fire type variable. your choices are listed in the FireType enumeration above. var fireType : FireType; //the shot type variable. your choices are listed in the ShotType enumeration above. var shotType : ShotType; //the shot sound of the gun var shotSound : AudioClip; // the out of ammo sound of the gun var OutOfAmmoSound : AudioClip; //the reload sound of the gun var reloadSound : AudioClip; // the particle effects that the gun has. usually particles that look like bullets, or a muzzle flash var ShotEmitter : ParticleEmitter[]; //the transform refrence to the tip of the gun var tipOfGun : Transform; // the transform refrence to the center of the sceen var centerScreen : Transform; //The following are the particles for different surfaces. class Particles { //do we use the tag system? var useTags : boolean = false; //Wood var WoodParticle : GameObject; //Metal var MetalParticle : GameObject; //Concrete var ConcreteParticle : GameObject; //Dirt var DirtParticle : GameObject; //Snow var SnowParticle : GameObject; //Water var WaterParticle : GameObject; //enemies var EnemyParticle : GameObject; // untagged var UntaggedParticle : GameObject; } //the refrence in the inspector to the above particles var Particles : Particles = Particles; //the array for using the non tag system. var HParticles : GameObject[]; //the name of the gun var gunName : String; // the key pressed to access this gun. NOT THE KEY TO FIRE, but the key that when pressed and this gun is not the current gun, it activates this gun and deacivates all other guns in the gun manager var keyToActivate : KeyCode; //the bullet mark of the gun var bulletMark : GameObject; //Do we leave a bullet mark? var leaveBM : boolean = false; // the elapse for the reload var reloadElapse : float; //how much power this will have on rigidbodies var pushPower : float; //the shot light var shotLight : GameObject; //the muzzle Flash prefab var muzzleFlash : GameObject; //roate raycast is for the way the model was rotated var rotateRaycast : ry; //icon is for gun manager var Icon : Texture2D; //@HideInInspector is a line used to make a public var not appear in the inspector. // the shots left before the clip is empty @HideInInspector var shotsLeft : int; //Are we shooting? //@HideInInspector var shooting : boolean = false; // the audio source private var Audio : AudioSource; //can we currently shoot? private var freeToShoot : boolean = true; //can we currently reload? private var freeToReload : boolean = true; //the clips left before the gun is useless. private var clipsLeft : int; //should we be shooting? private var shouldShoot : boolean = true; //are we reloading? private var reloading : boolean = false; //the last shot time private var lastShotTime : float; //rlInt will be used for reloading private var rlInt : float; //v3 is for rotate raycast private var v3 : Vector3 = Vector3.zero; //We call On Enable instead of Awake becuase this object(Gun) will be enabled multiple times throughout the game. function OnEnable() { //a for loop executes a certain line of code for a specified number of times. //Unless writing very specific code, use only for arrays. for(var i = 0; i < ShotEmitter.length; i++) { //sets the visual effects to off. ShotEmitter[i].emit = false; } //gets an audio source Audio = gameObject.GetComponent(AudioSource); //sets the shots left shotsLeft = clipSize; //sets the clips left clipsLeft = Clips; //if there is a projectile set, then make this be a projectile launcher if(projectilePrefab) { fireType = FireType.Projectile; } } function Update () { HandleInput(); HandleValues(); HandleReloading(); } function HandleInput() { if(Input.GetButton("Fire1") && shotType == ShotType.Full_Auto && fireType == FireType.RayCast && Time.time > lastShotTime) //full auto, raycast { lastShotTime = Time.time + fireRate; Shoot(false, false); } else if(Input.GetButtonDown("Fire1") && shotType == ShotType.Semi_Auto && fireType == FireType.RayCast) //Semi Auto, RayCast { Shoot(true, false); } else if(Input.GetButtonDown("Fire1") && fireType == FireType.Projectile) //Projectile { Shoot(false, true); } else if(Input.GetButton("Fire1") && shotType == ShotType.Full_Auto && fireType == FireType.Projectile && Time.time > lastShotTime) { lastShotTime = Time.time + fireRate; Shoot(true, true); } else { freeToShoot = true; } } function Shoot(oneShot : boolean, isProjectile : boolean) //function shoot handles the shooting logic. { if(freeToShoot) { //we are shooting shooting = true; //gets vars for raycasting var hit : RaycastHit; var fwd = transform.TransformDirection(v3); PlayShotSound(); if(!unlimited) { shotsLeft--;//subtract one bullet } if(!isProjectile) { GenerateShotGraphics(); Debug.DrawRay(centerScreen.transform.position, fwd*gunRange, Color.blue); if(Physics.Raycast(centerScreen.transform.position, fwd, hit, gunRange)) //The following lines are for raycasting. you can skip this if you want. { GenerateHitGraphics(hit, hit); ApplyForce(hit); } if(oneShot) { freeToShoot = false;//if we are semi auto, dont keep fireing } } else { //Instantiates the projectile. var instantiatedProjectile : Rigidbody; instantiatedProjectile = Instantiate(projectilePrefab, tipOfGun.transform.position, transform.rotation); instantiatedProjectile.velocity = transform.TransformDirection(Vector3.forward * projectileShotPower); if(shotType == ShotType.Semi_Auto) { freeToShoot = false; } } } //we are no longer shooting; shooting = false; } function GenerateHitGraphics(hit : RaycastHit, BMhit : RaycastHit) //HERE Is where we create the graphics for the HIT. NOT the SHOT! { //vars for the particles. var go : GameObject; var delta : float = -0.02; var hitUpDir : Vector3 = hit.normal; //leaves a bullet hole if(leaveBM) { if(BMhit.collider.tag == "Wood" || "Metal" || "Concrete") { if(!BMhit.collider.rigidbody && !BMhit.collider.isTrigger) { var bm = Instantiate(bulletMark, BMhit.point, Quaternion.FromToRotation(Vector3.forward, -BMhit.normal)); bm.AddComponent(BulletMark); } } else { return; } } //sends the apply damage message to the enemy that we hit if(hit.collider.tag == "Enemy") { hit.collider.SendMessageUpwards("ApplyDamage", Damage, SendMessageOptions.DontRequireReceiver); } if(Particles.useTags) { //changes the type of particle. switch(hit.collider.tag) { case "Wood": go = Instantiate(Particles.WoodParticle, hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; break; case "Metal": go = Instantiate(Particles.MetalParticle, hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; break; case "Snow": go = Instantiate(Particles.SnowParticle, hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; break; case "Concrete": go = Instantiate(Particles.ConcreteParticle, hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; break; case "Dirt": go = Instantiate(Particles.DirtParticle, hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; break; case "water": go = Instantiate(Particles.WaterParticle, hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; break; case "Enemy": go = Instantiate(Particles.EnemyParticle, hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; break; case "Untagged": go = Instantiate(Particles.UntaggedParticle, hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; break; } Destroy(go, go.gameObject.GetComponent(ParticleEmitter).maxEnergy); } else { for(i = 0; i < HParticles.length; i++) { var Go : GameObject = Instantiate(HParticles[i], hit.point, Quaternion.FromToRotation(Vector3.forward, hitUpDir)) as GameObject; Destroy(Go, Go.gameObject.GetComponent(ParticleEmitter).maxEnergy); } } }
//here is where the shot graphics are made. function GenerateShotGraphics() { //Instantiates the muzzle flash if(muzzleFlash != null) { var mf : GameObject = Instantiate(muzzleFlash, tipOfGun.transform.position, Quaternion.identity); Destroy(mf, 0.1); } //emits once the shot visual effects for(var i = 0; i < ShotEmitter.length; i++) { ShotEmitter[i].Emit(); } //creates a shot light if(shotLight != null) { var go : GameObject = Instantiate(shotLight, tipOfGun.transform.position, Quaternion.identity); Destroy(go, 0.1); } } //applys force to all rigidbodies that are hit. function ApplyForce(hit : RaycastHit) { var direction : Vector3 = hit.collider.transform.position - centerScreen.position; var body : Rigidbody = hit.collider.rigidbody; if(body) if(!body.isKinematic) body.AddForceAtPosition(direction.normalized pushPower, hit.point, ForceMode.Impulse); } function HandleValues() { if(shotsLeft <= 0) { shotsLeft = 0;//if we don't have any more bullets, we can't shoot freeToShoot = false; } switch(rotateRaycast) { case ry.left: v3 = Vector3.left; break; case ry.forward: v3 = Vector3.forward; break; case ry.right: v3 = Vector3.right; break; case ry.back: v3 = -Vector3.forward; break; } } function HandleReloading() { if(Input.GetButtonDown("Fire2") || Input.GetKeyDown(KeyCode.R)) { Reload();// pressed the reload button, reload. } if(reloading) { freeToReload = false; rlInt -= Time.deltaTime; if(rlInt <= 0.0) { reloading = false; shotsLeft = clipSize; freeToReload = true; } } if(reloading) { freeToShoot = false; } else { freeToShoot = true; } if(shotsLeft <= 0 && autoReload) //if we auto reload { Reload();// reload freeToShoot = false;//we can't shoot while reloading } if(clipsLeft == 0) { freeToReload = false;//if we don't have any more clips, then we can't reload } if(reloading) { freeToShoot = false; freeToReload = false; } else { freeToShoot = true; freeToReload = true; } } //the reload function. function Reload() { if(freeToReload) { if(clipsLeft > 0 && shotsLeft < clipSize) { PlayReloadSound(); reloading = true; rlInt = reloadElapse; } if(!unlimited) { clipsLeft--; } } } function PlayShotSound() { Audio.PlayOneShot(shotSound); } function PlayOutOfAmmoSound() { Audio.PlayOneShot(OutOfAmmoSound, 1); } function PlayReloadSound() { Audio.PlayOneShot(reloadSound); } function GetBulletsLeft() { return(shotsLeft); } function GetClipsLeft() { return(clipsLeft); }
function GetName() { return(gunName); } function AddAmmo(amount : int) { clipsLeft += amount; shotsLeft += amount; } function OnDrawGizmosSelected() { Gizmos.color = Color.red; var fwd = transform.TransformDirection(Vector3.left); Gizmos.DrawRay(transform.position, fwd gunRange); }
That... is a lot of code. Ohh BTW China called they want there wall back. :D
hey thanks man, i understand what you've done and yes i know of all of the documents ways of raycasting but i havent found one that lets you shoot towards a point from an object. you know the screenpointtoray, goes from the camera to a point, well im trying to do that but from an object and not the camera. i hope you understand and thanks again
AAAAH now i understand, yeh thanks man. To clear up all you need to do is get the Camer.main.transform.forward as a variable, then in raycast say Physics.Raycast(theobjectstransform, thecameravariabl, out hit); it shoots from the object then the forward position of the camera. thanks :)
Answer by StephanK · Apr 24, 2011 at 11:22 AM
If the center of the screen is you crosshairs you should do the cast from the center of screen in direction of the camera.
ive not got a crosshair yet, but when i put one on im thinking of making a smart one(one that adjusts)
Your answer
Follow this Question
Related Questions
FPS PISTOL 1 Answer
How do I make a gun project a particle? 1 Answer
Raycast hitting below mouse position :( 0 Answers
Shoot Projectile 0 Answers
Where can i find an easy raycast shooting tutorial for C#? 2 Answers