|
This isn't directly a Game dev question but more of a "What the gently caress is going on with Unity" one: I have a script attached to the player prefab which essentially handles the player's abilities. It assigns abilites to the buttons Q, E, and R, and when you press one it'll use that ability and put it on a cooldown. I have an AbilitySlot class which is instantiated for each button, which handles assignment of abilities and cooldowns, etc. So in the script's Update() I check for Q, E or R being pressed down, then call AbilitySlot.Use() which uses the current slot's ability. For some reason, when I try and call AbilitySlot.Use() nothing happens. I have a Debug.Log() set up to output whenever AbilitySlot.Use() gets entered, but that never triggers. I have no clue what's causing this, and Unity's not giving me any error messages whatsoever. Here's the relevant code: JavaScript code:
I'm completely stumped as to what's causing this!
|
# ? Sep 17, 2014 15:34 |
|
|
# ? May 12, 2024 17:12 |
|
So, the other logs trigger, but the Use log doesn't? e: Alternatively use KeyCode.R instead of "r"? http://docs.unity3d.com/ScriptReference/KeyCode.html vvv yep this! superh fucked around with this message at 15:44 on Sep 17, 2014 |
# ? Sep 17, 2014 15:42 |
|
^^^ "r" is not a defined key identifier in your Input Settings. Use KeyCode.R or define it.
|
# ? Sep 17, 2014 15:43 |
|
Ah, that's a better way to do that yeah. It recognises that R has been pressed down, outputs both "R is down" and "out of Use()", but not "in Use()". Other functions other than abilityR.Use() also don't seem to get triggered.JavaScript code:
e: Here's the full code (excluding the actual abilities) in case there's something really stupid I've missed. I can't see anything that would break it this horribly though. Miley Virus fucked around with this message at 16:03 on Sep 17, 2014 |
# ? Sep 17, 2014 15:51 |
|
Your coroutine isn't acting as a timer in the way you want. If you continuously held it down, it would work fine, I bet. Record a lastUsed time and check that against current time to see if it's available again.
Obsurveyor fucked around with this message at 16:19 on Sep 17, 2014 |
# ? Sep 17, 2014 16:17 |
|
This looks like a similar issue: http://answers.unity3d.com/questions/442037/unityscript-coroutine-not-running-when-called.html Is it because you're trying to yield from a class that isn't a MonoBehavior? Py-O-My fucked around with this message at 17:28 on Sep 17, 2014 |
# ? Sep 17, 2014 16:37 |
|
You can't start coroutines inside of update loop and assume they'll wait. Also I don't think you're actually starting the coroutine by just calling the method. I think you need StartCoroutine() wrapped around the Use() call. I'm not too strong with javascript in Unity so I might be wrong.
|
# ? Sep 17, 2014 17:22 |
|
Yeah looks like that was it, can't use yield from a non-MonoBehaviour class. Plus you can't yield from a static function (makes some amount of sense) which kind of screws over my entire method of handling temporary ability effects. Might have to reorganise the structure of this script somewhat, even though I'm not sure how else I'd do it without using that class structure.
|
# ? Sep 17, 2014 19:07 |
|
Miley Virus posted:Yeah looks like that was it, can't use yield from a non-MonoBehaviour class. Plus you can't yield from a static function (makes some amount of sense) which kind of screws over my entire method of handling temporary ability effects. Might have to reorganise the structure of this script somewhat, even though I'm not sure how else I'd do it without using that class structure. You could just make it a Monobehaviour. You'll have to do abilityR = gameobject.AddComponent<AbilitySlot>() instead of creating a regular object but it seems like it would be the same otherwise. Have Use() start a coroutine that contains the code you're already using. I made a nice little timer component that works that way and it works great, although I have no idea what kind of performance cost it has.
|
# ? Sep 17, 2014 19:48 |
|
Miley Virus posted:Yeah looks like that was it, can't use yield from a non-MonoBehaviour class. Plus you can't yield from a static function (makes some amount of sense) which kind of screws over my entire method of handling temporary ability effects. Might have to reorganise the structure of this script somewhat, even though I'm not sure how else I'd do it without using that class structure. So why are you using a coroutine instead of something like saving the time at which an ability was last used, and checking that against the current time whenever Use is called?
|
# ? Sep 17, 2014 20:29 |
|
JGTheSpy posted:You could just make it a Monobehaviour. You'll have to do abilityR = gameobject.AddComponent<AbilitySlot>() instead of creating a regular object but it seems like it would be the same otherwise. Have Use() start a coroutine that contains the code you're already using. Thanks, this worked perfectly. I had looked at AddComponent, but didn't realise that's what I needed to make that class as a MonoBehaviour. Chalk that one up to me not reading/watching many tutorials and diving in head-first. dupersaurus posted:So why are you using a coroutine instead of something like saving the time at which an ability was last used, and checking that against the current time whenever Use is called? It seemed easier that way? I imagine the way you and Obsurveyor described is more efficient, especially if Use could theoretically be called every frame (I don't know how expensive calling a coroutine is compared to a reg function). Something like that would allow me to do a countdown timer or something in the GUI easier too. I'll probably end up doing that so I don't end up loving myself over down the road.
|
# ? Sep 17, 2014 21:08 |
|
Miley Virus posted:Thanks, this worked perfectly. I had looked at AddComponent, but didn't realise that's what I needed to make that class as a MonoBehaviour. Chalk that one up to me not reading/watching many tutorials and diving in head-first. I think that's just one of those things you don't learn until you need it. I dove in head-first recently as well and that seems to be my experience with Unity in general. I think it works really well in that way since pretty much every possible question has already been answered if you can figure out what the hell to search for.
|
# ? Sep 17, 2014 21:19 |
|
Miley Virus posted:...you and Obsurveyor described is more efficient... Teach me to skim over things... I think the conceptual problem you have is that you're thinking of a StartCoroutine call as a normal function call, but it's not. (WARNING: the following may be talking out of my rear end) When you start a coroutine you're sticking it in a stack of stuff that Unity evaluates for changes whenever it runs (like a big update manager). So when you call StartCoroutine(Use()), Use() isn't actually called until Unity runs through the stack (to people more knowledgeable: is this at the end of the current frame, start of the next, fixed update, or voodoo?), even if Use() immediately breaks out because another Use() is still running. It's fine to use coroutines as timers for convenience for things that you don't really need to build a whole timer system for. But that's a "do X in Y seconds" thing, where your Use() is "do X and don't do it again until Y seconds," which is trivial to implement by just storing the time it was last called on. As you mention, that's extremely more useful because now you can tell where you are in the cooldown, not just that you're still in cooldown; all you're changing is your logic check from "has the coroutine finished" to "is the current time greater than last use time plus cooldown time".
|
# ? Sep 17, 2014 21:38 |
|
Coroutines seem awesome until you have to debug them and then you start scribbling notes down furiously in hopes to one day build a time machine so you can go back and stab yourself with a dull spoon.
|
# ? Sep 17, 2014 21:59 |
|
That's why I've (so far) not used them for anything super complicated.
|
# ? Sep 17, 2014 22:06 |
|
The worst I've ever done with them was a WaitForSeconds(0.1) because I needed to do something to a newly-created GameObject, but only after it had a chance to spawn and start up. Forgive me father, for I have sinned.
|
# ? Sep 17, 2014 22:30 |
|
dupersaurus posted:The worst I've ever done with them was a WaitForSeconds(0.1) because I needed to do something to a newly-created GameObject, but only after it had a chance to spawn and start up. Why not put that in the constructor of the Gameobject? Also it never hurts too much to do wacky stuff like that if you have a fixed platform (like Xbox 360) as you can generally expect the same CPU performance, but that could easily cause you an issue on something like Windows/Android where something could act in the background and draw CPU or on lower end devices.
|
# ? Sep 17, 2014 22:35 |
|
Stick100 posted:Why not put that in the constructor of the Gameobject? Also it never hurts too much to do wacky stuff like that if you have a fixed platform (like Xbox 360) as you can generally expect the same CPU performance, but that could easily cause you an issue on something like Windows/Android where something could act in the background and draw CPU or on lower end devices. I don't remember the exact situation, but that was the only way it was going to work without a massive restructuring that was never going to be able to happen.
|
# ? Sep 17, 2014 22:42 |
|
dupersaurus posted:The worst I've ever done with them was a WaitForSeconds(0.1) because I needed to do something to a newly-created GameObject, but only after it had a chance to spawn and start up. For shaaaaaaaaaaaaame.
|
# ? Sep 17, 2014 23:18 |
|
You do realize thats the diff between Awake and OnStart right?
|
# ? Sep 18, 2014 00:12 |
|
dupersaurus posted:Teach me to skim over things... Yeah, that makes some amount of sense now, thanks. Odd that they disguise it if you're using JS, but I guess it's stuff that new users (who would probably be using UnityScript or whatever) shouldn't have to worry about -- until it breaks and you have no idea why of course.
|
# ? Sep 18, 2014 01:21 |
|
xgalaxy posted:You do realize thats the diff between Awake and OnStart right? I'm going to try to find it at work tomorrow but I assure you it was a desperation move. Of course if I find it I'll probably go "oh duh" and kill myself, but I'm pretty sure it was something Unity was being stupid about.
|
# ? Sep 18, 2014 02:53 |
|
dupersaurus posted:I'm going to try to find it at work tomorrow but I assure you it was a desperation move. Of course if I find it I'll probably go "oh duh" and kill myself, but I'm pretty sure it was something Unity was being stupid about.
|
# ? Sep 18, 2014 03:52 |
|
roomforthetuna posted:Possibly a thing where you needed to initialize it based on some other object's state after its onAwake is called. Since the onAwakes happen in an arbitrary order, if you want one to go after another you have to do some tomfoolery. I found it and it wasn't as bad as I remembered it being. Process A uses a UI, triggers process B, then closes the UI. Process B needed the same UI so it was opening it immediately, but only for it to be closed by A. So I stuck a WaitForSeconds(0.75f) on B to let the UI close before opening it again. Hacky, but I didn't have the time to redo the system to do it properly.
|
# ? Sep 18, 2014 14:03 |
|
I've found for a lot of my objects that I just plain don't use Awake or Start if I need to make sure something initializes before something else. I've started just making my own public Init method for these objects and it works out pretty nice.
|
# ? Sep 18, 2014 14:47 |
|
joe_eyemobi posted:Are any of the asset store systems any good? I don't remember specifics but I have seen a couple in the past that allow for multidirectional gravity. I appreciate the response, but I managed to figure it out. Got the clamp working and put a script on the camera itself, rather than accessing it through a script. Allowed for the clamp to work as normal in any direction.
|
# ? Sep 18, 2014 18:02 |
|
Programmer Humor posted:One nice feature in Unreal I've found is you can do all kinds of procedural adding of Static Meshes based on variables in the construction script. These show up in the editor and can have static light calculated on them, etc, very nice. You can even have little vector variables you adjust by moving them around like any other object. As a follow up to this, in case anyone was curious, it's at least possible to generate everything you need in C++ and pass it to a blueprint construct script via variables or functions. Kind of dirty, but it works.
|
# ? Sep 18, 2014 21:32 |
|
What's the best/most correct way, in C++, to store items for an RPG or such? Say I have swords that the player can pick up, do I have an instance of the sword class for every different sword, even though they will all be identical, or do I have a single sword that can be accessed everywhere it is needed? Seeing as I'll probably do a debugging method to spawn items, it seems like I would have to write an enormous switch statement to handle what to spawn, while if there was a collection of 'model' items I could make it searchable and store the field with the item. I realise writing this there's probably a lot of parallels with how the Elder Scrolls games do their console item spawning, so just picture that if I've explained what I want badly.
|
# ? Sep 19, 2014 00:50 |
|
The standard way would be to have something like an ItemTemplate/ItemDefinition/ItemType class and an Item class. You have one instance of the ItemTemplate class for each type of item, such as Fire Sword +1, and one instance of the Item class for each actual instance of an item (my Fire Sword +1 with a blue gem and 17/30 durability, the ogre's Fire Sword +1 with ...). The Item object would reference the ItemTemplate object that it is an instance of.
Flownerous fucked around with this message at 01:02 on Sep 19, 2014 |
# ? Sep 19, 2014 00:58 |
|
I expect you want an instance of the Sword class for every item in the game yes. You might load some default swords from file and clone those every time you need a sword of some type. Since at the very least you want an individual sword to have it's own individual location, but also presumably spawn and delete them, maybe enhance it's attributes through enchanting or whatever, etc..
|
# ? Sep 19, 2014 14:56 |
|
Favor a flatter type hierarchy. Have just an Item class, with data members indicating that it can be equipped by sword users, that it has a sword icon, that it is called a Sword, what its stats are, etc.
|
# ? Sep 19, 2014 19:28 |
|
So have an Item class and differentiate them with the variables?
|
# ? Sep 19, 2014 19:52 |
|
Praseodymi posted:So have an Item class and differentiate them with the variables? Well, do the items behave differently, or do they do more or less the same thing but in varying quantities? It doesn't make much sense to have a different class for a sword +1 and a sword +2, but maybe a you can have a class called Weapon and one called Armor, both inheriting Item. It depends on how they should behave...
|
# ? Sep 19, 2014 20:45 |
|
Praseodymi posted:What's the best/most correct way, in C++, to store items for an RPG or such? Say I have swords that the player can pick up, do I have an instance of the sword class for every different sword, even though they will all be identical, or do I have a single sword that can be accessed everywhere it is needed? Seeing as I'll probably do a debugging method to spawn items, it seems like I would have to write an enormous switch statement to handle what to spawn, while if there was a collection of 'model' items I could make it searchable and store the field with the item. Go with Flownerous with this, that's pretty much the proper and most flexible way to do it. Usually all of the types of swords and their stats are in a file that you parse, which make up the templates that you read in. (See this.) The sword item will reference the template for its base stats, but each sword instance will keep track of modifiers that are unique to it and affect the template values (buffs, wear, player mods, etc).
|
# ? Sep 19, 2014 20:58 |
|
Flownerous posted:The standard way would be to have something like an ItemTemplate/ItemDefinition/ItemType class and an Item class. You have one instance of the ItemTemplate class for each type of item, such as Fire Sword +1, and one instance of the Item class for each actual instance of an item (my Fire Sword +1 with a blue gem and 17/30 durability, the ogre's Fire Sword +1 with ...). The Item object would reference the ItemTemplate object that it is an instance of. You should keep your shared properties and your individual properties separate. This reduces the overhead of having twenty Fire Sword +1 all duplicating the same info, and gives you the flexibility of being able to change your ItemTemplates easily, so if you later decide to rebalance your Fire Sword +1 it will automatically apply to all instances already spawned. You can read more about it here: http://gameprogrammingpatterns.com/flyweight.html Bongo Bill posted:Favor a flatter type hierarchy. Have just an Item class, with data members indicating that it can be equipped by sword users, that it has a sword icon, that it is called a Sword, what its stats are, etc.
|
# ? Sep 19, 2014 21:05 |
|
SupSuper posted:You gotta be careful with this though. You don't want to end up with a blob Item class that can represent everything from a sword to a pair of pants. Distinct behaviors should have distinct classes (either by inheritance or composition or etc). On the contrary, in some cases you do want to dispense with all pretense of object-oriented design and make everything from the items in your inventory to the UI out of completely generic Entities. This is not suitable for every type of game, however.
|
# ? Sep 19, 2014 21:10 |
|
Bongo Bill posted:On the contrary, in some cases you do want to dispense with all pretense of object-oriented design and make everything from the items in your inventory to the UI out of completely generic Entities. This is not suitable for every type of game, however.
|
# ? Sep 19, 2014 22:33 |
|
I'd suggest having an Item object (the item instance) with a pointer to an abstract ItemType class. Then you have subclasses of the ItemType based on functionality (weapons, armour etc). IMO this is the optimal solution for most cases - it's only un-flat where there actually is a divergence in functionality (ie - the game actually needs to treat armour differently to weapons). The only place it gets awkward is if there are specific instance traits that only certain ItemTypes can have (for example, a "Condition"/"Durability" trait for only armour). There are a few workarounds but they're all a bit clunky. pianoSpleen fucked around with this message at 16:30 on Sep 20, 2014 |
# ? Sep 20, 2014 16:27 |
|
pianoSpleen posted:The only place it gets awkward is if there are specific instance traits that only certain ItemTypes can have (for example, a "Condition"/"Durability" trait for only armour). There are a few workarounds but they're all a bit clunky. If you have a limited amount of types and want to be more strict, using an enum for all possible types is fine.
|
# ? Sep 20, 2014 22:08 |
|
|
# ? May 12, 2024 17:12 |
|
If I'm making a tick manager in Unity, should I be using C# events, or roll my own with linked lists or something? Events are drat handy, but I don't know what sort of extra performance overhead (if any) is there with them, with dozens of listeners frequently coming in and out.
|
# ? Sep 22, 2014 15:41 |