- Home /
Smart Crosshair
Hello Guys,
I'm working on an First Person Shooter and I was searching how to make a smart crosshair and I didn't found anything, I explain (what is my definition of smart crosshair) :
That become bigger when you shoot(not to much, just a touch)
Depending where you focus is size change
And it is basically this. I finally want how you can make it : with a script, raycast... And maybe some explanation or the final script (if is the good way to make it).
Best Regards,
Nbo
Answering your own question like this won't help. If you want to 'bump' just edit your question a little and save
I'm also looking for a Smart Crosshair for my FPS game. And i have seen that Dastarly Banana has a good one. But only the system how he makes that is to difficult. Don't understand it
... Then work on simpler things, until you reach the level at which you do understand it.
Answer by FLASHDENMARK · Jan 15, 2012 at 08:31 PM
A basic crosshair that spreads.
//Slap this script on to the main camera or similar and you'll have a GUI driven crosshair
#pragma strict
var drawCrosshair = true;
var crosshairColor = Color.white; //The crosshair color
var width : float = 3; //Crosshair width
var height : float = 35; //Crosshair height
class spreading{
var spread = 20.0; //Adjust this for a bigger or smaller crosshair
var maxSpread = 60.0;
var minSpread = 20.0;
var spreadPerSecond = 30.0;
var decreasePerSecond = 25.0;
}
var spread : spreading;
private var tex : Texture2D;
private var lineStyle : GUIStyle;
function Awake (){
tex = Texture2D(1,1);
SetColor(tex, crosshairColor); //Set color
lineStyle = GUIStyle();
lineStyle.normal.background = tex;
}
function Update (){
if(Input.GetButton("Fire1")){
spread.spread += spread.spreadPerSecond * Time.deltaTime; //Incremente the spread
Fire();
}else{
spread.spread -= spread.decreasePerSecond * Time.deltaTime; //Decrement the spread
}
spread.spread = Mathf.Clamp(spread.spread, spread.minSpread, spread.maxSpread);
}
function OnGUI (){
var centerPoint = Vector2(Screen.width / 2, Screen.height / 2);
if(drawCrosshair){
GUI.Box(Rect(centerPoint.x - width / 2, centerPoint.y - (height + spread.spread), width, height), "", lineStyle);
GUI.Box(Rect(centerPoint.x - width / 2, centerPoint.y + spread.spread, width, height), "", lineStyle);
GUI.Box(Rect(centerPoint.x + spread.spread, (centerPoint.y - width / 2), height , width), "", lineStyle);
GUI.Box(Rect(centerPoint.x - (height + spread.spread), (centerPoint.y - width / 2), height , width), "", lineStyle);
}
}
function Fire(){
//Carry out your normal shooting and stuff
}
//Applies color to the crosshair
function SetColor(myTexture : Texture2D, myColor : Color){
for (var y : int = 0; y < myTexture.height; ++y){
for (var x : int = 0; x < myTexture.width; ++x){
myTexture.SetPixel(x, y, myColor);
}
}
myTexture.Apply();
}
I spend a little bit of time on this and I managed to create the script above. The script is rather basic and there is a lot that you can do with it, but I guess it will do, for now at least.
Hello,
First Thank You. Second, I tweak a bit with your script and it's really good to make the crosshair. Now do you have any idea to make it focus ? To make it bigger for when it shoot I think about a function that basically said : Add 10 to spread, but I'm not sure if it will be smooth so...
I don't really get what you mean by "focus". Do you mean aim down sights or not? I edited the example to spread when you hold down right mouse button. Rather basic example, but it will get you going.
Focus : If the crosshair focus on an object that is close he'll be small and, if he's focus on an object that is far he's gonna be a bit bigger.
You will have to measure distance between the player and the object he or she is ai$$anonymous$$g at. Use raycast to retrieve information and use Vector3.distance to measure distance between you and the object.
It worked. Thanks for the help. I'm not sure if it'll help at all, but I'll post the conversion here for others to look at. As I said before, it's an extremely straightforward conversion.
using UnityEngine;
using System.Collections;
/// <summary>
/// A straightforward C# conversion of the JavaScript smartCrosshair (tentatively named)
/// Works similarly to original
/// </summary>
public class SmartCrosshair : $$anonymous$$onoBehaviour
{
#region Fields
public bool drawCrosshair = true;
public Color crosshairColor = Color.white;
public float width = 1;
public float height = 3;
[System.Serializable]
public class spreading
{
public float sSpread = 20;
public float maxSpread = 60;
public float $$anonymous$$Spread = 20;
public float spreadPerSecond = 30;
public float decreasePerSecond = 25;
}
public spreading spread = new spreading();
Texture2D tex;
float newHeight;
GUIStyle lineStyle;
#endregion
#region Functions
void Awake () {
tex = new Texture2D(1, 1);
lineStyle = new GUIStyle();
lineStyle.normal.background = tex;
}
void OnGUI () {
Vector2 centerPoint = new Vector2(Screen.width / 2, Screen.height / 2);
float screenRatio = Screen.height / 100;
newHeight = height * screenRatio;
if (drawCrosshair) {
GUI.Box(new Rect(centerPoint.x - (width / 2), centerPoint.y - (newHeight + spread.sSpread), width, newHeight), GUIContent.none, lineStyle);
GUI.Box(new Rect(centerPoint.x - (width / 2), (centerPoint.y + spread.sSpread), width, newHeight), GUIContent.none, lineStyle);
GUI.Box(new Rect((centerPoint.x + spread.sSpread), (centerPoint.y - (width / 2)), newHeight, width), GUIContent.none, lineStyle);
GUI.Box(new Rect(centerPoint.x - (newHeight + spread.sSpread), (centerPoint.y - (width / 2)), newHeight, width), GUIContent.none, lineStyle);
}
if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.$$anonymous$$ouse0)) {
spread.sSpread += spread.spreadPerSecond * Time.deltaTime;
Fire();
}
spread.sSpread -= spread.decreasePerSecond * Time.deltaTime;
spread.sSpread = $$anonymous$$athf.Clamp(spread.sSpread, spread.$$anonymous$$Spread, spread.maxSpread);
}
void Fire() { }
void SetColor(Texture2D myTexture, Color myColor) {
for (int y = 0; y < myTexture.height; y++) {
for (int x = 0; x < myTexture.width; x++)
myTexture.SetPixel(x, y, myColor);
myTexture.Apply();
}
}
#endregion
}
Answer by skully42 · Jan 17, 2012 at 01:15 AM
i dont know how to make that kind of crosshairs but what you can do is add the cross hairs in the game there is a crosshairs script in the game and the texture is the aim one i hope that helps
Alright here is what you have to do first make a gameobject and name GUI then search Crosshairs in the bar with everything in unity not your game then when you find that drag it into your GUI gameobject click on you gameobject and you will see the crosshair script with a texture that is not there in the texture folder you will see the aim one then drag that into the crosshairs script and you are done if you have any questions just ask i will help i look at my email almost everyday to see if there is a new comment
Answer by luozitian · Jan 14, 2012 at 08:24 AM
Here is my solution for your question: 1. use Screen.showCusor = false to hide mouseCousor 2. use GUI.DrawTexture for your crossHair 3. if shoote, replace one bigger texture when press fire button,you can adjust the size by GUI.DrawTexture function. 4. use Raycast to gernerate one ray from fire position and if it is hit something with tag,for example "Enemy", replace the texture that belongs to "Enemy"(you need assign tag "Enemy" to your Enemy object.)
Thank You for your answer, but I already figure it out. $$anonymous$$y problem is really when he shoot and he focus. Is your technique is good when he shooting (smooth).
Actually the accepted answer is a good starting point. Thanks for both the topic and the answer.
But is it only me, or the code is actually kinda messy? It doesn't do what it should in the long run. For example public variables width and height are not affecting width and height... not surprisingly, since they are used in GUI calls when we deal with pixels, but they have values like 1 or 3...
As I said - no offence to the accepted answer's author, but let's embrace more clean and healthy code :) I'm posting my cleaned-up version. It doesn't apply actual spread change (anyway, it should be counted in some other controller), but it would be easy enough to implement it, the parameter is included into the count and made public:
using UnityEngine;
using System.Collections;
public class Crosshair : $$anonymous$$onoBehaviour {
public bool drawCrosshair = true;
public Color crosshairColor = Color.white; //The crosshair color
public int lineLength = 10; // Length of the crosshair line (in pixels)
public int lineWidth = 1; // Width of the crosshair line (in pixels)
public int spread = 20; // Spread of the crosshair lines (in pixels)
private Texture2D tex;
private GUIStyle lineStyle;
void Awake ()
{
tex = new Texture2D(1,1);
SetTextureColor(tex, crosshairColor); //Set color
lineStyle = new GUIStyle();
lineStyle.normal.background = tex;
}
void OnGUI ()
{
Vector2 centerPoint = new Vector2(Screen.width/2,Screen.height/2);
if(drawCrosshair){
GUI.Box(new Rect(centerPoint.x,
centerPoint.y - lineLength - spread,
lineWidth,
lineLength), GUIContent.none, lineStyle);
GUI.Box(new Rect(centerPoint.x,
centerPoint.y + spread,
lineWidth,
lineLength),GUIContent.none,lineStyle);
GUI.Box(new Rect(centerPoint.x + spread,
centerPoint.y,
lineLength,
lineWidth),GUIContent.none,lineStyle);
GUI.Box(new Rect(centerPoint.x - spread - lineLength,
centerPoint.y,
lineLength,
lineWidth), GUIContent.none, lineStyle);
}
}
//Applies color to a texture
void SetTextureColor(Texture2D texture, Color color){
for (int y = 0; y < texture.height; y++){
for (int x = 0; x < texture.width; x++){
texture.SetPixel(x, y, color);
}
}
texture.Apply();
}
}
How does the code not do what it is supposed to? In the long run? It is an example of a crosshair. The specific setup is irrelevant as it could be done in countless ways.
And no offence taken - yet your provided code seems to add nothing but less of what the OP asked.
And just to be picky your lineWidth is applied incorrectly - it does not center as it should.
And yes. Having incremental, decremental operations and alike in OnGUI might not be very advisable, yet it fulfills its purpose.
:)
I'm not sure, why my answer was posted as a comment to an irrelevant question, but so be it :).
OrangeLightning, my answer is somewhat off-topic - you are right, the cursor is not so smart... But as I said - the "smart" logic should be counted somewhere else (even though, it is perfectly fine by me to apply some logic in onGUI() call for demonstration purposes).
And yes you are right, my mistake, that I'm not centering by "lineWidth". If somebody will move my "comment" to a real answer, I'll fix it :)
About the "mess" and "fulfills its purpose" contradiction: Do you think it is a good and sound order of things when by "width" you mean crosshair line width in pixels, but at the same time "height" means crosshair line length and is measured in some relative to screen size units? And then spread is again is counted in pixels? Come on... it is not intuitive at all, and shatters my picture of the world to peaces :)
This should be at least commented and shown clearly by variables names, but in fact - better be refactored (so this is what I did, for the sake of anyone using your snippet in future).
As I said, big thanks to you, anyway - it's a very good starting point.
@Wiseman17 If you want someone to be notified of a comment reply you have to begin the comment with @theirNameAccuratelySpelledHere
. Additionally, in my experience you can't tag more than one person in a comment, so if you want me to be notified as well as OrangeLightning, you need to do two comments. Just FYI :)
Answer by CrilleStyles · Feb 25, 2015 at 10:27 PM
You can always have 2 images of a crosshair, one normal and one spread out. use Gameobject.SetActive while moving/shooting etc. I'm doing it in my games at least.
Your answer
Follow this Question
Related Questions
Get GUITexture to follow ScreenPointToRay ray cast 1 Answer
Creating A Crosshair in Unity 4.6.2? 4 Answers
Reduce Draw call for Multiple GUI Textures with same Texture 1 Answer
Simple GUI In game 1 Answer
Yet Another GUI vs. Raycasting question. 2 Answers