Unity Tutorial - Drag & Drop Tutorial #2 [RPGs, Card Games, uGUI]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey folks quality in here and welcome to another episode of our unity tutorial on how to make a drag and drop system using the unity UI system that was added in 4.6 so when we left things off we were in a state where we could drag this card around and sort of just have it go wherever it wanted but our goal here is to make something that looks a little bit like a magic the gathering or hearthstone kind of setup where we've got a hand and then we've got an area that we can drop the cards into and we want them to sort of lock into those places it's not the sort of game where we want things to just be able to be dragged wherever they want although this is potentially completely valid for a different kind of game that's why there's no one-size-fits-all so we're going to do a couple of things here first of all I'm going to take my card over here I'm going to make a prefab out of it and I'm just going to remove it from the board here so that we can arrange a few things I mean to make um what else am I going to do I don't like the fact that the screen is quite this wide so just to make it look a little bit saner let me go ahead and just set an aspect ratio here I like the sixteen by nine that's your standard computer widescreen it just makes I know makes it a little bit more attractive to me we're going to make some more adjustments that's relatively soon so what we're going to do is we're going to set up two areas we're going to start off I'm going to right-click on the canvas go to UI I'm going to add a panel again the only difference in a panel and an image is they have slight lead from default so the panel is going to be semi-transparent and by default is and X anchored to all four corners of the canvas it's not exactly what we're looking for here though and take this panel I'm going to go to the anchor presets I'm going to hold alt and shift and I'm going to force it to be glued to the bottom of the screen then and again I'm sorry I didn't necessarily explain it I'm going to make sure I'm in 2d mode right 2d Millwood is on and make sure I have my rectangular selection tool not my normal transform tool it'll be my rect transform tool and we're going to bring the top down actually we know our cards are 200 units tall let's go ahead and make the hand about 210 units tall so this is going to be my hand this is where cards get stored up with anyone make a second area well note you know we'll start with the hand for now so what does it mean to have a hand of cards well if I go and drag my card prefab back into the scene oops make sure it's on the canvas there we go I put it here I mean yeah all right so right now it's just sort of hovering around its parented to the canvas if I add the card the hand well that's all good and fine but there's nothing that stops me from sort of dragging it wherever I want including when I'm playing the game I can hit play I can still drag it wherever I want and I mean that's not really what we want and what happens when we start to get more than one card in here then I've got it what like start arranging them by hand mmm that's not what we want we would like these to be automatically set up so what we're going to use on our hand we're going to use a layout there are three automatic layout tools I think there's just a three there's a horizontal layout a vertical layout and also a grid a grid is maybe the sort of thing you'd want to use in a role-playing game like something like a Diablo for example for us horizontal layout seems to make a lot of sense it's going to be a bit weird when I put it in though horizontal or actually there that was a good search layout grid layout horizontal layout vertical layout and also something called a layout element which we will be looking at so if I go ahead and trigger the horizontal layout on the hand something weird will happen but okay everything has been stretched out and if I add more cards we can see pretty clearly what's going on right the layout is automatically stretching everything to use the full possible width of the card and into end just stretch it out and make it nicely laid out well nice is questionable but it is definitely lay it out we don't want it to look this way so what what are we going to do well in the hand in the horizontal layout group script we have the option of disabling the force child of expansion in width and height now this looks all of a sudden it broke let's delete these and drag a new card into our hand it's still broken so why is that happening well because the card itself even though this kind of annoys me even though the rect transform here has a width and height and even though we've turned off the force child expansion on the horizontal layout group it still assumes once we put a card in here you'll notice we can't modify the width and height it sort of gets stuck and you know we can't necessarily tweak things which is weird maybe has something with anchors I don't think that's the case the solution to this is to add something called let's remove this card we're going to work simply on the prefab you can add something called a layout element on here and what this script does where this component does is give a hint to the system of hey if I'm in a layout group I got certain rules so that I want followed for example I would like to say that my height and width is not flexible at all so now let's put the card in here still doesn't quite work which strikes me as super odd but what you can do is specify a preferred width and height by default this will set the width and height that your rect transform is and now let's see what happens when you drop it in there there now it stays the way it is if I go ahead and duplicate this card a few more times okay that looks much better if I turn off the flexible width and height but I still have the preferred then it also works like okay so what if I do the force all right now even though I've got a preferred it will still do the force what if I leave the force whoops what if I leave the force on on the hand and go back to the card and specify not only do I have a preferred height and width but I'm specifying that I'm not at all flexible then it still doesn't do it I'm like it's it seems a little counterintuitive that like you sort of have to set all the things but now that we've said all the things we've told the hand do not force the child expansion and on the card we set a preferred width and height and indicated the system that we are not at all flexible we can also ignore the layout but I think that we did not ignore all aspects of the layout I might be wrong though let's put the force back on let's say ignore layout drop the card in there yeah no it ignores it completely doesn't even arrange itself the way we want so make sure the force expansion is off do not ignore the layout make sure we have a preferred height and width set the flexibility to off and now if we have cards in here everything looks the way that it probably should on the hand itself I'm going to say the child alignment over here instead of being upper left we're going to say middle Center there we go that's looking a lot better okay I like that a lot anything else you might want to adjust well we could change the spacing between cards because we've got a bit of a rounded image on our car B's that UI sprite there's a little bit of a technically but we could also change it in the hand here we could set a spacing of say four pixels in between the padding is not the padding around each child element but rather around the object itself we don't really need to adjust that because we've sort of allowed for it with the height so that's going to be okay all right so we've got that now it looks good we add more cards they they get added nicely we undo them they get removed nicely it looks pretty good if we hit play and we start dragging this Black Lotus around what do you think might happen well as it turns out really not much we can still drag things wherever the hell we want why is that well it's because normally if something isn't a grid you really shouldn't be moving the objects and the grid doesn't reset the position of anything unless the the number of children that are sort of parented to this hand in this case change right it's perfectly happy to let you move things around and that's all there is to it but if I take one of these cards take this card here if I remove it by the hand if I dress drag it onto the canvas itself boom it does refresh the grid positioning if I take this and give this card and put it back on the hand it goes back where it is it's worth noting that by default it gets added to the end of the list you can see here card is here if I reorder it in the inspector to say there now it's actually the first item on the list in this grid but the drag doesn't this is not really what we're going to want is it so what do we want to do well it's actually going to be the next step is going to be relatively simple let's say what happens when we drag we're in play mode if we start dragging let's remove this card from this this hand let's remove it from the hand hierarchy it's pretty easy to do go back to our script we've got this on begin drag event over here so on drag is we're actually adjusting your position but when we start the dragging what if we do something like um this I like to specify this for my transform just so that I'm like really conscious of what object I'm modifying obviously that this doesn't have to be there at all it's just it's just my personal little thing that so I don't get confused later on when you're doing something like this draw transform equals some other object dot transform you know it you can you can do it or not do it but one of things we can know to transform is set a parent so right now the parent is the hand object but instead of the hand we want to pack and we want to excuse me parent ourselves to the canvas we don't just want to set our parent to null we want to set ourselves to the canvas now we know in this structure that the canvas is basically the parent of our parent so I guess we can just do this we're sort of hard-coding in things right now but you know let's let's say that that's okay so we're going to set our parent to our current transform dot parent parent let's do this and see how that works then we'll clean it up a little bit so we're going to hit play so I'm going to take the leftmost card which if we walk watching the inspector is this card right over here I'm going to take this and start dragging it boom I'm now parented to the canvas instead of the hand and as soon as I did that the grid rearranged itself to deal with the fact that it now has a missing thing and again if I let go then it'll I look I clicked a second time if I whoops if I let go then I just stay there right now if I click again it's going to parent itself to its parents parent which means it won't even be part of the canvas anymore which means it won't draw anymore okay so obviously this hard-coding is no good but it shows the the general idea let's go ahead and say this okay normally in one of these games if you drag something this sort of an invalid location let's say I drag it over here and there's not really any drop spot over here right just empty space and I let go usually what it will do is bounce itself back into its original position so let's do that actually before we continue let's go ahead and colorize these guys that card is going to be maybe not that cool gonna be a little reddish this one here is going to be maybe a little bluish ooh maybe a grey dark dark blue there we go like that next card here we're going to make green next card here it's not attractive but you know what can you do I will make it sort of maybe a golden golden color like this okay now we can clearly see each card as things get reordered right so again if I take let's say I take out the blue one it'll be quite clear there we go the blue one is gone and the red one and green one have Skoosh together okay I like that I'm going to save the scene so what we're going to do we're going to save our parent do something like this transform this is um this is I've been ordering to call this original parent or maybe a parent to return to it's a bit wordy to return to but it's pretty clear what's going on we're going to make sure this is set the null by default just to be clear that shouldn't be important before we change our parent let's save parent to return to we're going to save our old parent and then we're going to repair it ourselves to our parents parent a bit wordy but that's what we're looking to do when we stop dragging let's go ahead and set our parent back to where we came from so parent to return to will do that so now what will happen as I'm going to pull out the blue card is going to be D parented as soon as I let it go it'll be repented to where it was before and GIP step to the end of the list red green yellow there we go put out the pink one and then release it it shows up at the end of the list there we go that's you know all right we're digging that that's feeling a little bit like maybe things should work that way let's go ahead and get a second drag zone going on so we've got our hand let's go let's start off by I'm going to duplicate the hand delete the cards that were inside of it and we're going to call this one the minion draw or card draw area or maybe the tabletop hey I like that table top right you put the cards on the table top I'm gonna go ahead and just move it up it's still going to stay anchored to the bottom of the screen I'm just going to move it up to be a little bit higher like so tell you what we'll change the background color to sort of a greenish area there so that we can clearly see it when it's going on okay so now we have this other tabletop I can if I want I can drag cards into it right it'll have some cards on there cool and I and drag one of these black lotuses and drop it it'll go there okay good and I can still drag these guys and when I let go they still return to their parent but obviously what we would like right now is to be able to grab one of these cards drop it here and have it show up in this list instead of this one over here so how do we do that how do we get the card to lock itself to a different parent how do we get the card to be conscious of where it's dropping well there's two different ways of doing it one way well there's lots of different ways of doing it but there's there's sort of two general approaches just like we've gone and added these events here right these drag handlers on our draggable we can create a new script let's call it something like drop zone which seems like a relatively good name and there's more things we can listen to using Unity engine dot event systems just like there's an eye drag handler there is a eye drop handler which requires you to have a function on here it's got to be a public void on drop and it takes pointer event data same as before so let's go ahead and I think that's right oh yeah yeah we're going to go debug log on drop two we're going to add our name under opt come on quill you can do this game object dot name okay let's go on our tabletop we're going add the drop zone and actually on the hand we'll add one as well because we're going to want one on both of those as before instead of implementing an interface instead we could have added an event trigger component here and then wired things up but I again because I'm worried that I'm going to forget to wire a future event triggers I really like the idea of just implementing this interface and then it'll just work this will just get drop if ever something is being dragged using the built-in unity UI drag system if something is being dragged and gets dragged on top of this object and then released this will trigger there's a few other things we can do there's an eye pointer enter and exit handler that you can use so that you know when something has come in and out which is kind of useful it'll trigger anytime you move the pointer in and out whether you're dragging or not but you can test to see if something is being dragged which is cool but we'll just leave it for now okay so let's watch the console log over here I'm going to grab the yellow card over here you can see we're getting lots of on drag commands actually let's go ahead and get rid of the on drag just a little too noisy there you go will just comment it out for now that'll be much much better okay grab this so we got the on begin drag now I'm going to drag it over here and I'm going to release and we're going to see two things or not we only see one thing really we only get the on end drag the table top has the dropzone script which should be listening here let me let me verify using my my previous version I drop handler public void on drop this should be sufficient why is that not public void public ranjana hold on hold on no I'm doing the wrong one let me double check something here let me check sorry about this I'm part of the problem as always is that I keep trying to sort of strip it down to its bare minimum and I guess just like over here where we're just doing the drag handler it's possible that I drop handler is not sufficient let me respond to on pointer enter and I pointer exit I'm actually thinking that we may need to listen to both of these in my test I had those on pointer enter and yet we need one of those let me duplicate this let's see for this is actually going to be required and then exit if it is I will be quite surprised because it seems like the sort of thing that shouldn't be required okay no it's definitely not working hmm that doesn't make much sense to me what's going on on public void on drop pointer vent data is here we should spit out the name it's an eye drop Handler drop zone drop zone is here drop zone is there oh I know what's going on here's another thing let's go and add some more debug I know exactly what's going on okay this is good I like it when we sort of screw things up a little bit and we can explore something that will get confusing let's add some extra debug messages to the pointer enter and exit we don't need these but it'll actually illustrate a point very well now if I mouse around you can see here on pointer enter on pointer exit those are triggering over here great and down here that's lovely we get lots of that kind of spam let's go ahead and clear this log here we'll still get one more as we come in over here let me grab this Black Lotus and now move around notice we're no longer getting pointer and enter and exit messages why is that we're getting them here but we're not getting them when we're dragging well the reason is while we're dragging this card it's blocking all the mouse messages basically every every frame the UI system is basically doing a ray cast from your mouse position and seeing what it hits and it uses that to trigger events like for example on enter on pointer enter and exit right again like this doing ray Kasten is like okay we're moving here when I'm dragging the card the ray cast from my mouse pointer is hitting the cards I'm dragging therefore it's not able to send the signal to everything else that hey the pointer is in you and when I release the mouse it sends the on drag command but my drop zone never knew that the card or the mouse was on it so it didn't actually get triggered an on drop so what we have to do is when we are dragging a card we have to stop the card from eating all of the Ray casts from the mouse luckily this is very easy to do there is a component you can add to something called a canvas group now a canvas group allows you to alter things on a card for example this is really important when you try to make something become invisible right because if I want to I could take this card it's like okay color oh I can make it transparent great let's make the card completely transparent oh it's not doing that because right because of the way that I have things let's grab one of these cards right this let's grab one of the white ones over here nice and visible let's make this card transparent we're going to take the color we're going to drop the Alpha down to nothing well all I did is change the transparency of the specific object that I have here for example I'm not trying to change in the transparency of everything below it so what do I do do I have to go and change the transparency of every single one no as long as I've got a canvas group oh oh it's cuz I'm playing there which means that the connection to the prefab is completely broken all right once I got a canvas group on an object so I've got two here I've also got on a prefab what you can do is change the Alpha of the canvas group and it changes absolutely everything beneath it at the same time but it's also get these cool options here for blocking array cast which by default is on if you turn it off now this object will no longer respond to ray cast now I can't just turn it off because I think it'll also yet disables the dragging so that's no good we don't want that so we want to have it on normally but when we start our drag so here the draggable when we start doing the drag we're going to get our component canvas group oops canvas group and we're going to set block ray cast to be false and then when we stop dragging we're going to turn it back on like this so now let's go back to the console log over here and hit play we'll get the one message that we've entered now when we start dragging we will still get our pointer enter and exit messages because it's ignoring the card and now when I drop it here we should see the on drop in the the log BAM on drop to tabletop it's actually very worth noting that the on drop command triggers before the on end drag does which we can use for different things so now we've got a few different things now the card itself is aware of when the dragging stops right this is the card knowing that it's no longer being dragged but also the thing that we're being dropped on top of can get a message to say hey something's dropped on you so there's a couple of different ways we can work this one let's say this parent to return to let's say I make this public and then in my drop zone how do we know what dropped on to us well the event data here we can even change this something like event data dot selected object I think it's selected object no not selected object pointer drag pointer drag this is the object being dragged and I believe it's the game object so was dropped on like that let's go ahead and disable these pointer enter and exit messages because they're way too noisy let's see this so I drag this one and drop it here card three was dropped on tabletop BAM exactly what we're looking forward to do we're gonna grab this card and drop it down here card one was dropped on hand wonderful so now we know event data dot poor net drag that's the object that we're dragging around we can get the component on this thing called draggable we're just going to assume it exists technically what you might want to do is you know one of these call this if D not equal to null you know this this is this is a good idea and I guess I'll leave this in but in our little demo we know there's going to be a draggable on there so we can say something the dot parent to return to equals this so what we're going to say oops nope this dot transform right of course so what we're saying is when you get dropped on here since the on drop responds first it's going to override the parent to return to and set it to the thing that I'm dropping onto is in this case the tabletop what happens if I let go here BAM a pretty slick now we can drop drag and drop between these two zones currently we have no filtering to say whether that's a legal drop or not again if you're making some sort of role-playing game you're going to want to do something like you know the card itself that draggable might want to have something like you can use yeah something like an enum maybe right eeen um oops I hit insert something like a weapon it's basically what slot oh this is going to be called slot there we go it's going to be weapon head chest legs feet and then we say something like public slot type of item have a default be like a slot dot weapon or something like that and then with your drop zone you can do the same sort of thing and say what it is and then in here you can make sure that they match one another right if okay if these not equal to null and assuming I have should be a draggable dot slot type of thing I'd say what mine is and then here if typeof item is equal to d dot type of item then and only then do we set the parents all right so let's do something like that this is actually we can test this and let's not exist draggable dot slots 11 there we go so by default everything is set the weapon so everything should work exactly the same as it was there we are that's ok but let's change the tabletop to a different type this is a disaster your chest slot for example now we're gonna hit play and I will no longer be able to drag things onto the tabletop that I can't it's not valid now technically these two white cards are still flagged as weapons and the hand slot down here is flagged as a weapon slot so I should be able to drag two down there but then I can't put anything back because nothing is set to a chest but if I grab one of these cards which one is that one this card is the red one if I change this to chest then I should be able to drag this one up to here but not down here yeah very simple way to implement and one of the things you could do is have a slot called inventory inventory and here you can say by default these drop slots might be of type inventory so if if I'm if the item type matches or I'm an inventory right inventory can accept all kinds of items so if we're an inventory slot or our type of slots match then we allow people to drop on to us and then our tabletop will go ahead and change the tabletop slot to inventory and now everything should be draggable there we go so these weapons I can put in the inventory and this is a weapon slot so technically I can do all those alright so those are the kind of ideas obviously it doesn't apply to our card game system but I hope you you know this sort of thing makes sense to you I'm going to go ahead and delete all this to clear it up but you can go those sorts those sorts of filters and what you can do and you're on pointer enter and exit is you can have things maybe glow if it's a battle a valid slot or the other thing you can do is on begin drag you could go and find all the drop zones in the game right because you can do something like game object find objects of type drop zone this will give you a drop zone array right something like this and then you can loop through all these and every one of them that is a valid slot for your current item that you're dragging you make them glow and then when you end drag you do the same thing you go through all the zones and turn all the glow off that way everything that's a valid spot for you to drop on to just is highlighted simple simple little concept that is kind of a cool thing to do we're going to leave it out of this demo just because I don't think it's going to be required for our purposes but I hope you find basically at this point you can make a full RPG system and when you and drag and it gets applied to a slot so again either here and draggable or in drop zone you can then apply some logic like oh if it's a helmet of +2 strength then make sure to apply the +2 strength at that point from you know whatever's appropriate your system now note right now we're using these drop zones here to be able to identify what so the drop zone itself is telling the draggable hey you are on me and I am your new parent and we're doing some things ok the drop zone is using that logic it doesn't have to be that way the other way you could do it is um in your how would we do this trying to remember the the code what you can do when you drop here is your event system then system dot current raycast all there we go raycast all it needs a event data basically because the event data contains the position the place where you are okay it needs an event data because that contains the position of the mouse that's basically all that this is required for and then it wants a list you can see it wants a generic a list of raycast results what this will do is this will do a ray cast in a place wherever the mouse is right and except for anything that has the raycast or ignore raycast was it called blocks recast any except for things that have this turned off right by default this is turned on for everyone so it's okay it will do raycast wherever your mouse is and it will tell you every single object that's underneath there and so instead of using the drop zone to tell the draggable hey you're on top of me instead the draggable on end drag can do a raycast and say hey what's underneath me it'll get a list of everything that's underneath it and then it'll be able to loop through all those and then apply some sort of logic depends on what kind of game you're making for us this is going to be pretty fine although a good example of this sort of behavior is maybe if one of these was a spell that had to be targeted on something I said still complaining about slots not the real if this was a spell that had to be targeted on something that might be a really good example especially as you're dragging around you might keep doing ray casts or again you can have the pointer enter and exit right these drop zones with pon pointer enter on pointer exit I mean every one of these cards make sure maybe the card shouldn't be a drop zone oh maybe it could be right if you drag a spell over a card and you let go instead of adding this card to the table top instead it just targets the thing that you're dragging on top of and fireballs it right you'd have to put in that kind of logic you know is the card I'm playing a minion or is it a spell how do I want to work things but you know there there you have it that is um that's the gist of it now we are going to go ahead and do one more tutorial because there is a very cool behavior in my demo if I make sure I saved this let me open the other one the one I did for practice do-do-do-do-do-do in my little demo I mean I can click on this deck to draw cards but that's that's not relevant that's you know that's not a thing at all in my demo when I pull off this black dragon card you'll see it leaves a space there and in fact I can reorder my cards because in ours every you play a card it gets added to sort of the end of list right like this gets added to the end of the list in our current demo so far but what if you wanted add it on left or in the middle how would you do that well stay tuned for the next episode folks thank you very much for watching of course if you're new to my videos do be sure to subscribe I mean you're watching the second or third video or whatever we are right now so I hope you've done that at this point make sure to drop a like and of course if you look down below you can find a link to download all of the source code for these projects from my website and I hope you find it useful see you next time folks when we do this
Info
Channel: quill18creates
Views: 145,907
Rating: undefined out of 5
Keywords: Unity (game Engine), Game Engine (Software Genre), programming, tutorial, first, person, shooter, first person shooter, fps, howto, how to, beginner, guide, unity, unity 3d, unity 4, physics, blender, 2d, 3d, quill18, quill, multiplayer, Blender (Software), ui, gui, ugui, drag, drop
Id: P66SSOzCqFU
Channel Id: undefined
Length: 33min 57sec (2037 seconds)
Published: Sun Mar 22 2015
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.