playMaker

Author Topic: Classic Point & Click Interface[SOLVED]  (Read 11629 times)

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Classic Point & Click Interface[SOLVED]
« on: September 03, 2012, 03:11:27 PM »
Hey all - I posted this over on the Unity forums, but I recently grabbed PlayMaker to try and get a little forward momentum.  Here's a quick breakdown of what I'm looking to do:

I'm in the process of designing out a classic point and click interface (mousewheel will transition through Walk, Look, Use, and Talk) and I'm thinking I'm going to have to write a few different scripts to tie things together...I need some pointers in terms of where to look for some of this stuff.

I already have the mouse click to move working with an animated model (the player) complete with locomotion (although it's pretty rough around the edges).

I know I'll have to write a quick script to disable the OS mouse cursor and have my own set of GUI elements that transition from state to state. I guess the big topics for me are:
1) I need to create a global script that has GUI elements changing along with state changes using the mouse wheel.  I'm having a hard time finding a method of using the mouse wheel in this way with PlayMaker.
2) I need to figure out how to cancel player moving if they are using the "Look", "Use", "Talk" mouse-click states.
3) I need to create a separate script that has variables for "Look", "Use", and "Talk" that I would attach to colliders/objects/characters/etc..., so players get the proper feedback when clicking on objects throughout the world. This would be how I handle "hotspots" like an old point and click adventure.
4) Figure out how to actually display the information of "Look", "Use", and "Talk". I'm guessing I'll probably just have to have the variable point to a GUI element that might be referencing text data somewhere?

I've been looking around to find some info that would help me out on this stuff.  Anyone have some reference/resources they could point me towards to get me in the right direction?  I've been looking around on forums and wikis and haven't come across what I'm looking for...

Thanks for any info!  Much appreciated.
« Last Edit: January 02, 2013, 06:04:58 AM by jeanfabre »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: Classic Point & Click Interface
« Reply #1 on: September 04, 2012, 04:21:02 AM »
Hi,

 do you have a game example of point and click, so that I can get an indea of what you are after?

bye,

 Jean

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #2 on: September 09, 2012, 01:16:57 PM »
Hi there -

Basically, following the old point and click adventure paradigm like classic Sierra On-Line or Lucasarts games.  The main cursor changes from a "Walk" icon, to a "Look" icon, to a "Use" icon, to a "Speak" icon, and then if you choose something from your inventory, it changes to that item's icon.

These are transitioned by mousewheel, number keys, and/or the right-mouse click.

Thanks!

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #3 on: September 09, 2012, 03:35:31 PM »
Okay - so, I now have the icons transitioning on right-mouse click.  The next thing I want to do is have the "Walk" icon ONLY drive the clickcharactercontroller (tied to the locomotion tutorial from the unity site: http://unity3d.com/support/resources/unity-extensions/locomotion-ik) that I setup before I got PlayMaker.  Is there a simple way to do that or will I have to reconstruct the controller which points to the locomotion system within PlayMaker?  I've gone through the tutorial vids online and am unclear on this.  I was thinking I could add a Playmaker FSM to the player object where the clickcharactercontroller and the locomotion system live that basically just waits for a message to be called from my InputManager Playermaker FSM object.  That way, I could maintain that a left-click ONLY makes the player move when I want it to (right now, it doesn't really matter what I'm doing, a left-click will ALWAYS make the player move to the location that I am pointing to).

Would that work or am I high?

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #4 on: September 09, 2012, 07:15:01 PM »
Another quick update: I did get this sort of working.  I'm using the "Enable Behaviors" Action, enabling it on the "Move" state, and disabling it on all the others.

I am running into a bug where if I change states before the player completes its path, it'll just keep walking past the destination point.  If I go back to the "Move" state, it'll turn around and head back to the destination that it just passed...so I'm trying to figure out how to say "finish your destination, but still don't let any other state make you move".

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: Classic Point & Click Interface
« Reply #5 on: September 10, 2012, 03:25:28 AM »
Hi,

 this is likely a case where you need to have more Fsm, and maintain flags about what the player or th efeature is doing. So upon a command, check what th eplayer is doing and if you have to wait until completion, you simply raise a flag, wait for the event ( the feature shoudl fire an event on completion), then check for that flag and if raised, proceed.

does that make sense?

bye,

 Jean

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #6 on: September 10, 2012, 10:57:50 PM »
Yeah, that totally makes sense...I'll just need to figure out the workflow from PlayMaker to look for those flags, I guess.

Thanks,  jeanfabre!  Much appreciated!

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: Classic Point & Click Interface
« Reply #7 on: September 11, 2012, 05:41:50 AM »
hi,

 it's a simple FsmBool that you set to true when you detect that you need to wait for completion.

when you receive the completion event, check that this bool is true, and if true, process with whatever was pending.

Have a go, and come back to this thread if you get stuck,

bye,

 Jean

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #8 on: December 25, 2012, 08:42:38 PM »
Hey all - Happy holidays!

I'm bringing this thread back from the dead as I had to take a break on my project for a little while since work got a little crazy.  I was able to make sure the player completes their path even if the user changes states in the middle of the motion.

I realized when I said that I was using "Enable Behaviors" that I was doing it on a specific gameobject basis and not in a global way.  How would I leverage this a bit more universally?  Meaning, how would I make sure that the cursor would do a check when I move the mouse over any object to see if they contained the specific components that I am looking for?

Thanks!

kiriri

  • Hero Member
  • *****
  • Posts: 506
Re: Classic Point & Click Interface
« Reply #9 on: December 26, 2012, 05:24:54 AM »
"mouse pick" every frame + "has component" every frame.
Mouse pick is primarily just a raycast, so it's ok to run it every frame.

Is that what you were looking for?
Best,
Sven

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #10 on: December 26, 2012, 11:26:17 AM »
Well - it doesn't seem to recognize on mouseover.  Right now here are the settings that I have for this particular portion of the FSM

ACTION: Mouse Pick
Ray Distance 1000
Store Did Pick Object: None
Store Game Object: None
Store Point: None
Store Normal: None
Store Distance: None
Layer Mask: 0
Every Frame is ON

ACTION: Has Component
Game Object: Use Owner
Behavior: LookStateText (this is the script component that I attach to any object that needs to be "looked at")
Remove on Exit is OFF
True Event: FINISHED
False Event: FINISHED
Store: None
Every Frame is ON

ACTION: Enable Behavior
Game Object: Use Owner
Behavior: LookStateTest
Component: None
Enable is ON
Reset on Exit is ON

In my brain, this would mean that when the mouse is over any object that has a LookStateTest script component while using the "Look" Game Cursor and the player clicks on it, it would enable the LookStateTest behavior.

Obviously, I'm missing something and am feeling pretty dumb...any pointers?

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #11 on: December 26, 2012, 11:51:59 AM »
Although, I should mention that these scripts that I am attaching to objects are javascripts that I wrote outside of Playmaker...Should I reconstruct them as Playmaker FSMs and attach those to the objects instead of the javascripts?  I'm wondering if that would make things a bit more clear...

kiriri

  • Hero Member
  • *****
  • Posts: 506
Re: Classic Point & Click Interface
« Reply #12 on: December 26, 2012, 12:26:10 PM »
Looking at your states, there seem to be some confusion about how playmaker works. You need to think more like a programmer I think.

Alright, let's start with the basics  ;)
Most of the actions take input and give output. Therefore you have to think less modular, and more "If I do this, I get that, which then again , I can use as input in the next action".

As a practical example.

We're in frame 1. The mouse pick action kicks in. It creates a ray from the mouse coordinates into the scene. It then collides with a GameObject there. That means, whatever it collides with, that gameObject will be "under" the mouse cursor.
So of course, to check more specific things, we need to know what the current gameObject the ray collides with actually is. To do that, we create a gameObject variable and put it in the Mouse Pick action as "Store Game Object".
This is all that's happening for this frame in the MousePick action. So the action lets PlayMaker continue to the next action in the state, which is the Has Component action.
The first variable of the action is for input. Whatever we put into it, it will then check if the component is on that gameObject. By default it is set to "Use Owner", which in this case we do not want, because the Owner is the gameObject the FSM component belongs to. Instead, we change it the the gameObject variable which contains the output from our MousePick action before.
Now, apart from input and output we can also send events based on the result of an action. The HasComponent action will either say "Yes, such a component indeed does exist on the specified gameObject!", which programmers call a "True" statement, or it'll say "Nah, nothing like that on there!", which is called a "False" statement.
So if the statement is True, the true event is sent by our action. If it is false, the false event is sent.
In case you missed that, events are the things you can click on to drag a connection to other states. You create them by right clicking at a state.
Now, that understood, any action that returns the same event for both True and False events is entirely abundent. It's like saying if an apple is green, it tastes great. And any apple that is not green, tastes great also. The result of that statement would be "Any apple tastes great", hence the irrelevancy of the previous two statements.

So back to the HasComponent action, we want it to do stuff only if the gameObject under our cursor has that specific component. So we leave the False event empty, and set the true event to FINISHED. Then we create a transition on that state and use the FINISHED event for it.
We then create a new state, which we connect the FINISHED transition to. That new state will contain the EnableBehavior action. Again, the gameObject input of that action needs to be set to the gameObject variable we created earlier and which contains the result of our mouse pick.
Now, if your behavior does not appear in the dropdown next to the behavior input in the action, it is actually a component. Luckily the same action also supports components/objects. Just select the component in the inspector and drag it into the Component input of the action.
Enable defines whether it should activate or deactivate the behavior/component. Now, Reset on Exit does exactly what it says, and we definitely don't want that. With it set to True/On it would reset the changes once you leave your current state. Since we're going to leave the state immediatly after the action is finished, turn it off, else it will do nothing at all.


Now, what these 3 actions do, is in the first state, they will once per frame (60 times per second) first check what's below the cursor, then check if that gameObject contains the needed Component. If it does, it will go on and enable the behavior, if it does not, it will wait 1 frame and try again.

Attention: What we've just created is an infinite loop! What that means is that the computer tries to run it infinitely fast, which will crash unity. Why? Well after the mouse is over a gameObject with the right component, it will go to the next state immediatly. There it will finish its' work and trigger FINISHED automatically (FINISHED is the only event that gets executed automatically when all the actions in a state are done.). This will send it back to the first state, and it will run it again, but it won't pause for one frame as it would have if the first state would loop itself using the "every frame" option of the actions. Since the whole process takes only a split second, the mouse cursor has obviously not changes so the first state again returns true, and sends the FINISHED event.
All this loops forever and Unity tries to do this all in one frame. So because it's just one frame, it won't update your mosue, even after minutes. This makes unity freeze for you, even though it's actually just looping your 2 states forever at maximum speed.

We can fix this with the "Next Frame" action. It works just like the everyFrame option on actions. Once a new frame starts, it will send an event. If we put it at the bottom of our second State and set the event to FINISHED, it will then always wait one frame after activating the behavior and only then return to the first state to check again.

Now, this may be all nice and dandy, but you'll note that everything happens if the mouse is over the gameObject, and it does not care in the slightest if you just clicked or not.
To fix that, we create another state, which we will also make the start state (right click - > set start state). In this new third state, we will put a "Mouse button up" (mouse button down if you prefer) action. That action checks every frame if the mouse button went up or down, and if it did, it sends an event. So we create another FINISHED transition and set the event in the mouse button up action to FINISHED. we connect the state with our very first state. Then we look at our second state (the one with enable behavior) and connect the FINISHED event there to our new start state.

Now what happens is, in the start state it will check the mouse state every frame. If the mouse button goes up/down, it will go to the next state. in that state it will get the gameObject under the cursor and check its' components, if the component exists it will continue. If it does not, it will loop that state until there is such a gameObject under the cursor.
That is definitely not what we want. We don't want to click anywhere in the screen and then move our mouse over an object after our click only to have it continue as if we actually clicked on it. So what we do is we create another event, let's call it FAILED in the events tab. then we create a new transition in our state (the one which checks for the component) and then we use that event as our False Event. We connect it to our start state again, so it can once again check if the mouse goes up/down and try again once it does.

Phew, and that's it. Detailled explanation on the basics of playmaker :) Do ask for specifics if something isn't clear.

Best,
kiriri
« Last Edit: December 26, 2012, 12:27:42 PM by kiriri »
Best,
Sven

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #13 on: December 29, 2012, 05:41:35 PM »
Holy CRAP.  Thanks, kiriri!  I'm away from my main Unity rig for a few days, but I'll start diving in and seeing what sort of trouble I can cause with all of this excellent info.  Thank you very much!!

cronkie

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Classic Point & Click Interface
« Reply #14 on: January 01, 2013, 07:13:30 PM »
Kiriri -

I just wanted to do a quick follow-up to let you know I have the basic prototype of this now working!  Thank you so much!

I have a "Walk" state which allows the player to go to a location based off of left-click.  If you right click, it transitions to a "Look" state that will now do a raycast and search for a "Look" script on any object (instead of a specific object) and will fire off windowed text if you click on an object that has the "Look" script attached.  Likewise, if you right click again, it will transition through "Speak" and "Use" states; all of which behave like the "Look" state.  After you right click through the "Use" state, it transitions back to "Walk"  (disabling previous behaviors as it goes) and is ready to cycle through again.

Now, one thing that I will have to figure out is if I have two objects with these scripts attached and I "Look" at one and then immediately "Look" at the other, the description text stacks on top of each other.  As of now, I need to complete the Look script on Object 1 (clicking somewhere on screen that ISN'T Object 2) and then click on Object 2.  I'm guessing I'm going to have to use some sort of countermeasure when I'm engaged in one behavior and if I try to engage in the next one, it disables all components of that type before it starts another.  I'm guessing I'll probably have to setup another global variable for this, but I haven't jumped into this just yet.

After I get that established, then I'll start connecting this to an actual Dialogue/Inventory system (I'm using Unity Dialogue Engine now).

Thanks again for the kick in the pants!  It was very helpful.