Search Unity

Radial Menu

Discussion in 'Scripting' started by Hi_No_Te, Nov 24, 2012.

  1. Hi_No_Te

    Hi_No_Te

    Joined:
    Apr 1, 2012
    Posts:
    23
    I am trying to make a Real-time Battle Radial Menu, where the user can click on an enemy, and a Radial Menu appears with possible icons of their known attacks and spells. I cannot get the Radial Menu to stay where it originated, rather it follows the mouse using Event.current.mousepos for x and y. Another thing is how would I use textures that can detect if the mouse is hovering above it, for the player to know what they're selecting? I know Unity build in GUI buttons work for that, but I don't want to make individual buttons for many attacks and spells.

    Thanks for the help.
     
  2. DayyanSisson

    DayyanSisson

    Joined:
    Aug 4, 2011
    Posts:
    623
    We're going to see some code or maybe an explanation of exactly what you're doing.
     
  3. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Stash the original opening position in a variable, then draw it based on that position instead of the mouse's current position.
     
  4. Hi_No_Te

    Hi_No_Te

    Joined:
    Apr 1, 2012
    Posts:
    23
    Like:

    if(MouseButton(2)){
    This-variable = Event.mouseposition;
    DrawTexture(at This-variable, etc...);
    }
     
  5. Hi_No_Te

    Hi_No_Te

    Joined:
    Apr 1, 2012
    Posts:
    23
    That itself is inside function OnGUI() { }.
     
  6. Bunzaga

    Bunzaga

    Joined:
    Jan 9, 2009
    Posts:
    202
    When you click the game object, you store the objects transform as a variable. Then you convert this objects position + any offset you want to apply to screen coordinates to get the proper center position for the radial menu.

    You need to think about it... if you store the mouse position, then the camera moves, the mouse position is no longer significant in any way.

    You would also need to use sin / cos to determine the radial positions around the object. You could either divide it equally, based on the number of icons to display, or else start at position 0, then work your way around to position 1, then position 2.

    Here is an example I wrote up, I hope it helps!
    Code (csharp):
    1.  
    2. #pragma strict
    3. private var selected:Transform = null;
    4. public var skillMax:int = 5;
    5. function Update () {
    6.     // clear the GUI buttons
    7.     if(Input.GetButtonDown("Fire2")){
    8.         selected = null;
    9.     }
    10.     if(Input.GetButtonDown("Fire1")){
    11.         var hit:RaycastHit;
    12.         if(Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), hit)){
    13.             selected = hit.transform;
    14.         }
    15.     }
    16.     // move camera around a bit
    17.     if(Input.GetAxis("Vertical")){
    18.         transform.position.y+=(Time.deltaTime*Input.GetAxis("Vertical")*10);
    19.     }
    20.     if(Input.GetAxis("Horizontal")){
    21.         transform.position.x-=(Time.deltaTime*Input.GetAxis("Horizontal")*10);
    22.     }
    23. }
    24.  
    25. // how much to spread the icons apart
    26. public var offset:Vector2 = Vector2(100, 100);
    27. // offset where icon 0 begins (90 is the top)
    28. public var degOffset:float = 90.0;
    29. // width and height of the icons...
    30. public var iconSize:Vector2 = Vector2(48, 32);
    31.  
    32. function OnGUI(){
    33.     if(null != selected){
    34.         // amount to offset each icon around the center
    35.         var radialTic:float = (360/skillMax)*Mathf.Deg2Rad;
    36.         // used to offset where '0' starts
    37.         var radOffset:float = degOffset*Mathf.Deg2Rad;
    38.         // position of the object
    39.         var objPos:Vector3 = camera.WorldToScreenPoint(selected.collider.bounds.center);
    40.         for(var i = 0; i < skillMax; ++i){
    41.             var rad:float = (i*radialTic)+radOffset;
    42.             var guiX:float = objPos.x+Mathf.Cos(rad)*offset.x;
    43.             var guiY:float = objPos.y+Mathf.Sin(rad)*offset.y;
    44.             // hug the screen
    45.             guiX = Mathf.Clamp(guiX, 0, Screen.width);
    46.             guiY = Mathf.Clamp(guiY, 0, Screen.height);
    47.             if(GUI.Button(Rect(guiX-(iconSize.x*.5), Screen.height-(guiY+(iconSize.y*.5)), iconSize.x, iconSize.y), "Test"+i)){
    48.                 Debug.Log("Clicked Button "+i);
    49.             }
    50.         }
    51.     }
    52. }
    53.  
    Change line 40 to this:
    Code (csharp):
    1.  
    2. var rad:float = -(i*radialTic)+radOffset;
    3.  
    To get it to rotate around clockwise instead of counter clockwise.
     

    Attached Files:

    Last edited: Nov 24, 2012
  7. Hi_No_Te

    Hi_No_Te

    Joined:
    Apr 1, 2012
    Posts:
    23
    I got what you mean, Bunzaga, and I had to adapt your script to fit mine. It's a bit unrefined for now, but it works lol;
    Thank!