Forum rules - please read before posting.

Feature request: Action based on mouse-click location

edited March 2014 in Engine development
I'm trying to set up a spell system similar to the quest for glory games where you click on any location on the screen and a fireball flies to that point. I don't believe there is currently a way to use the mouse click position for any actions besides walking, and while it can probably be scripted easily, it would be nice to have a feature which allows an action to reference the mouse click position. Just an idea! Thanks

Comments

  • A custom action should get the job done, I think.  You can get the mouse position from the PlayerInput script:

    GameObject
    .FindWithTag (Tags.gameEngine).GetComponent <PlayerInput>().mousePosition

    Follow the guide in the manual to learn how to create a custom Action - you can use the ActionTemplate.cs script as a basis.

    To run it, you should be able to do it with Menus: create an invisible button that takes up the whole screen, and display it when in "fireball mode".  Set the Button's Click Type to Run Menu Action List, and set the Menu ActionList to use your new Action.
  • Thanks, I'll see if I can figure out how to set up that action.

    However, I was under the impression that when a button is present on the screen it acts a barrier to raycasts. The click location is detected via raycast, right? Would the click location be able to be determined if I am clicking on a menu button?

    Also, my ideal plan is to have a fireball inventory cursor which causes the fireball to fly to and explode at the various click points, but when the fireball cursor is clicked onto a hotspot, it will run an appropriate action for that hotspot, and not necessarily send a fireball to the click point. If the menu is present, it would not be able to determine when a hotspot is being clicked on, I assume. 

    Alternatively, I'm wondering if I can adapt the clickmarker script to perform this function depending on the active cursor. Would that be easier/possible? 
  • Well, you'd have to create a new Raycast - the custom Action would have to take care of everything, using the mouse position as a starting point.

    You can certainly create a new Icon in the Cursor Manager for your Fireball interaction.  If you don't have the Menu on, it'll be detectable - I was under the impression you wanted to use the Menu to toggle on "Fireball mode". Otherwise, yes, you'll probably have to edit the clickmarker script. It's called PlayerInteraction.  Check the Update function, which determines which click function to run - in your case, it'll probably be MouseOverHotspots.
  • Hmmm I'm not sure I have the necessary scripting skills for this, but I guess I'll give it a try. I think I have an idea of how to go about it- I'm going to try to use parts of the transform object action and the clickmarker script to make a new action which ideally translates the object to the mouse click location which is detected by the clickmarker script.

    I'm also trying to create a background hotspot which is selected whenever any regular hotspot is not being clicked. I assume if I create a giant hotspot and put it behind all of the scene objects, it can act as this background hotspot, so that I can "look" at what room I'm in, or cast any of these spells towards any location in the room. Do you think this can be done?

    I'm probably going to end up with some weird unworkable Frankenstein conglomeration of a script, but I guess this is the best way to learn!

    Thanks for the help, if I can't figure it out I'm probably just going to run the fireball actions for particular hotspots, which works, but isn't as fun as being able to shoot fireballs at anything in the scene!
  • You can certainly create a big Hotspot behind the others - you might want to parent it to your MainCamera, too, so that you don't have to worry about changes in camera angle.  You can also set the length of the Raycast in the Settings Manager.

    Something this specific would likely need custom scripting, but I hope that you can get by without it (or at least something simple enough).
  • So I've duplicated and modified the ActionTransform script to try to create an Object: Transform To Click Position action, but I've run into some problems. 

    I have tried to keep the formatting of the action script as close to the ActionTransform script as possible and the new script is in, but when I try to refresh the actionlists I get two errors :

    Instance of ActionTransformClickLocation couldn't be created. The the script class needs to derive from ScriptableObject.
    UnityEngine.ScriptableObject:CreateInstance(String)

    and

    NullReferenceException: Object reference not set to an instance of an object
    ActionsManager.RefreshList () (at Assets/AdventureCreator/Scripts/Managers/ActionsManager.cs:139)

    I've looked at the manual and I've tried pretty much everything I can think of but these errors keep appearing when I try to import the new action.

    Just for reference, the only modifications I made to the ActionTransform script were:

    Replacing the "ActionTransform" terms with "ActionTransformClickPosition"

    Declaring a private PlayerInput variable

    Added a function:
     public Vector3 GetMouseCoordinates (Vector3 targetVector)
    {
    Ray ray = Camera.main.ScreenPointToRay (playerInput.mousePosition);
    RaycastHit hit = new RaycastHit();
    return(hit.point);
    }

    to the main ActionTransformClickPosition function directly after the run function

    Also, I commented out the newVector gui component (because ideally the action uses the detected click position).

    So first off, do you have any idea why the instance can't be created? And do you think the action would work as I hope, as long as I only call it when a hotspot is clicked on? 

    Thanks as always!
  • Shouldn't see a problem in principle.  But without your full code on display there's not much I can do!  Be sure to rename the script itself to ActionTransformClickPosition.cs, and check that it dervices from the Action base class.
  • Ah! Good call, I had mistakenly named the file ActionTransformClickLocation.cs! Now it still doesn't work perfectly (i.e. the fireball is not being sent to the right place) but at least I can debug the script a lot more easily. Thanks!
  • edited March 2014
    Sorry to keep bothering you about this, but I'm almost done. I got the action working pretty well- it sends the fireball to the mouse location when I click on a hotspot which runs the action. The only additions I've made to the transform script to get it done are the following at line 106:

    if (transitionTime > 0f)
    {
    Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    RaycastHit hit = new RaycastHit();
    if (Physics.Raycast (ray, out hit)) 
    {
    Debug.Log(hit.point);
    linkedProp.Move (hit.point, moveMethod, transitionTime, transformType);
    }

    This works pretty well, but there is a problem if the mouse is moved away from the click location quickly enough- the new mouse position is used to send the raycast, so the fireball is sent to the moved. So as long as I leave the mouse over the click point for about a half a second, it works as it should.

    Is there any way you can think of to store the click location as it is clicked, rather than call the mouse location about 0.2 seconds after the hotspot is clicked? Or if that isn't the problem, any idea what is? 

    Thanks though, this is working much better than I could have hoped with my scripting knowledge! AC is really great!
  • Is this because of the time gap in between clicking the Hotspot, and the Action running?  You might want to try setting the Hotspot's [b]Player action[/b] to [b]Do Nothing[/b], to reduce it.

    You could also try a bit of a hack whereby you use the position of the Hotspot menu, assuming you've left it's Position Type to OnHotspot.  Try this:

    Rect menuRect = PlayerMenus.GetMenuWithName ("Hotspot").GetRect ();
    Vector2 mousePos = new Vector2 (menuRect.x + (menuRect.width / 2), menuRect.y + (menuRect.height / 2));
  • Well changing to do nothing may have reduced that time gap but it's still there. And I tried the hotspot menu hack, but I must be doing something wrong because it's not getting the correct world coordinates. I have it set up like this:

    if (transitionTime > 0f)
    {
    Rect menuRect = PlayerMenus.GetMenuWithName ("Hotspot").GetRect ();
    Vector2 mousePos = new Vector2 (menuRect.x + (menuRect.width / 2), menuRect.y - (menuRect.height / 2));
    Debug.Log (mousePos);
    Ray ray = Camera.main.ScreenPointToRay (mousePos);
    Debug.DrawRay(ray.origin, ray.direction * 10, Color.yellow, 100f);
    RaycastHit hit = new RaycastHit();
    if (Physics.Raycast (ray, out hit)) 
    {
    Debug.Log(hit.point);
    linkedProp.Move (hit.point, moveMethod, transitionTime, transformType);
    }

    And the debug log is showing me that there is some disconnect between the mouse position and the raycast direction- when I move the mouse lower on the screen, the log is showing me that the y coordinate of the mouse is increasing as it should, but the drawn ray somehow moves up on the screen. Looks like the coordinates are getting inversed somehow. 

    Oh well, it's not that important- it was working well enough before and I think it will do. Maybe I can come up with some other fix on my own after messing around with scripting a bit more. Thanks for the help though!
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.