As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/
Options

Game Dev - Unreal 4.13 Out Now!

17273757778100

Posts

  • Options
    MorninglordMorninglord I'm tired of being Batman, so today I'll be Owl.Registered User regular
    edited November 2015
    I've only done a bit of C++ like over a decade ago now.
    I never got really deep.
    I've only just started learning C# (basically just what is in these tutorials).
    What's the problem with it compared to C#?

    Morninglord on
    (PSN: Morninglord) (Steam: Morninglord) (WiiU: Morninglord22) I like to record and toss up a lot of random gaming videos here.
  • Options
    DelzhandDelzhand Hard to miss. Registered User regular
    At the moment it's that C++ devs seem incapable of choosing good variable names. The larger issue is that I can't figure out how to convert unreal's FString to a format that can be split by strtok.

  • Options
    KupiKupi Registered User regular
    edited November 2015
    EDIT: Holy shit huge. Sorry. Whole post spoiled for sympathy to the scrollwheel.

    Hello again, Penny Arcade Game Development thread. It's been a while. I'm back with a report on what I've been up to, game-making wise. This is going to be long. Bear with me; I'm counting all this toward my NaNoWriMo word budget...

    I sort of dropped off of my studies in the Unreal Engine, largely due to falling into a bit of a depressed slump after taking a project I'd been working on for two years out behind the shed. I could write an entire blog post about that situation in and of itself, but since I've already done that elsewhere I don't feel like repeating myself here. In any case, I've gone back to an old project that I discussed in this thread before, the JRPG combat engine based on Nim. That was... not exactly what you'd called finished, but it had a lot of work put into it, and both out of boredom and out of thinking I could do better, I decided to go back and revise it from the ground up with what I've learned from the first attempt.

    To refresh your memories of the core premise, the game does not use any RNG, contrary to typical JRPG conventions. Instead, events like critical hits and misses are laid out on a timeline, akin to a board game, and every character ability causes a different amount of advancement on the timeline. So one move might advance by 2 and land on a critical hit space and get triple power, while a different move might advance by 3 and land on the miss space just past that and fail completely. Furthermore, the timeline is shared between the player and the computer, meaning the move you make on your turn will determine what's available to the enemy. You might actually want to take the miss on your turn just to prevent the enemy's most powerful attack from landing on a critical hit. Furthermore, damage-over-time effects are represented as tokens on the timeline that cause damage as you pass them, so DoTs will tick faster if you use a lot of high-advancement moves, while they'll tick slower if you use moves that only advance by one or two spaces a turn.

    In my original pass, characters were able to freely use any ability they had, and furthermore, to elect a target out of the entire enemy party. Unfortunately, this had pretty dire performance implications when it came to getting the AI to play the game intelligently. Half the reason I went with this fully-deterministic set of rules was, after all, to have an AI actually act predictably and choose its actions wisely, rather than the random option selection that is more typical of the genre. The problem is that the search space grows exponentially in the number of ply (turn depth), and when you're talking about exponents, you want as low a base as you can possibly get. If every character on a team has two moves, and there are four members of each team, and each move can attack each other enemy... that's a worst-case base of 32. When you go ten turns deep into the analysis, that's 1,125,899,906,842,624 possible game states. Uheheheh.

    So this new version of the game was designed with an emphasis on reducing the base of exponentiation by limiting the number of options available to either side. There are two major mechanics that work to that end. The first is what I call "Pokemon swapping", after the Pokemon games, where you're only allowed to fight with a single monster out of your team of six at a time. Now, the game treats each party as an ordered list, with each ability targeting only a specific position in the list. This is typically the front of the enemy party, but actions can also target the last member of the enemy party, the second member, all enemies, and so on. Either way, there is no targeting phase to action selection. You pick action you want to use, and whoever owns that action uses it. Second, I added a mechanic I'd previously excised from JRPG tradition-- Skill Points. In the new version of the game, actions can have a Skill Point cost, and by convention every character can (and must) have exactly one action that costs nothing and one action that has a Skill Point cost. In this way, the number of actions available to a side, assuming all characters are on their feet, ranges from 4 to 8, and no higher. Raising anything to the tenth power is always going to kick your ass, but a search space of 1,073,741,824 has two fewer commas. I call that a win.

    Another issue I addressed in a new way this time around was the creation of new character actions. In my previous rendition, I handled everything in code. I'm increasingly learning to treat "I handled everything in code" as a big, flashing Check Engine light when it comes to game development. Mind you, I had a nice little class hierarchy, so that creating new skills tended to just be slapping together a bunch of classes I'd already written with a lot of overrides given new values, but it also meant that any time I wanted to create a new ability, it meant bug fixes and re-compiles. How barbaric! So instead, I reduced the code to just a small set of basic objects-- the core ones being Effects, which represent some kind of transformation of game state (like an attack between characters, stats going up or down, or swapping characters in the party order), Rules, which are allowed to examine, modify, delete, or issue new Effects, and Nodes, which are the things that sit on the timeline and are allowed to issue either Rules or Effects. Then, I created a dedicated language / file format that describes those objects, and read them in manually. Any time I want to create a new skill, I type just the things that actually matter to the definition of the skill itself, and nothing else. It's... liberating.

    For those who are hanging on the edge of their seats over this post (and I sort of pity you if you are?), I've tossed my current test files beneath the spoiler below as an example of the syntax. It's purely forward-parsing, and uses all whitespace as a delimiter. Brutish, but effective for my purposes.

    Actions.txt -- describes actions
    ACTIONS
    {
    	ACTION
    	{
    		NAME { Hurt Attack }
    		ADVANCEMENT 1
    		COST 0
    		EFFECTS
    		{
    			ATTACK
    			{
    				REQUIRESLIVINGSOURCE
    				SOURCEMUSTBEFIRST
    				TAGS
    				{
    					Hurt
    				}
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { FIRST ENEMY }
    				POWER COMBATANTPROPERTY SOURCE POWER
    				DEFENSE COMBATANTPROPERTY TARGET DEFENSE
    				NUMERATOR 2
    				DENOMINATOR 1
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Hurt Attack 2 }
    		ADVANCEMENT 2
    		COST 0
    		EFFECTS
    		{
    			ATTACK
    			{
    				REQUIRESLIVINGSOURCE
    				SOURCEMUSTBEFIRST
    				TAGS
    				{
    					Hurt
    				}
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { FIRST ENEMY }
    				POWER COMBATANTPROPERTY SOURCE POWER
    				DEFENSE COMBATANTPROPERTY TARGET DEFENSE
    				NUMERATOR 2
    				DENOMINATOR 1
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Power Up }
    		ADVANCEMENT 3
    		COST 0
    		EFFECTS
    		{
    			GAINSP
    			{
    				REQUIRESLIVINGSOURCE
    				TAGS
    				{
    					SPGain
    				}
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { CURRENT ACTOR }
    				AMOUNT 1
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { You Die Now }
    		ADVANCEMENT 2
    		COST 3
    		EFFECTS
    		{
    			POISON
    			{
    				REQUIRESLIVINGSOURCE
    				SOURCEMUSTBEFIRST
    				TAGS
    				{
    					Poison
    				}
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { FIRST ENEMY }
    				POWER COMBATANTPROPERTY TARGET MAXHP
    				DEFENSE 0
    				NUMERATOR 1
    				DENOMINATOR 1
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { SP Explode }
    		ADVANCEMENT 2
    		COST 0
    		EFFECTS
    		{
    			LOSESP
    			{
    				REQUIRESLIVINGSOURCE
    				SOURCEMUSTBEFIRST
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { CURRENT ACTOR }
    				AMOUNT COMBATANTPROPERTY SOURCE SKILLPOINTS
    				CONTINGENTEFFECTS
    				{
    					ATTACK
    					{
    						REQUIRESLIVINGSOURCE
    						SOURCEMUSTBEFIRST
    						SOURCE PARENTSOURCE
    						TARGET COMBATANT { FIRST ENEMY OF SOURCE }
    						POWER MULTIPLY 
    						{ 
    							LEFT RESULT
    							RIGHT COMBATANTPROPERTY SOURCE POWER
    						}
    						DEFENSE 0
    						NUMERATOR 1
    						DENOMINATOR 1
    					}
    				}
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Revenge }
    		ADVANCEMENT 3
    		COST 2
    		EFFECTS
    		{
    			ATTACK
    			{
    				REQUIRESLIVINGSOURCE
    				SOURCEMUSTBEFIRST
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { FIRST ENEMY }
    				POWER SUBTRACT
    				{
    					LEFT COMBATANTPROPERTY SOURCE MAXHP
    					RIGHT COMBATANTPROPERTY SOURCE HP
    				}
    				DEFENSE 0
    				NUMERATOR 1
    				DENOMINATOR 1
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Heal Me Later }
    		ADVANCEMENT 2
    		COST 0
    		EFFECTS
    		{
    			MAKENODE
    			{
    				DISTANCE 3
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { ALLY ACTOR }
    				NODE
    				{
    					EFFECTS
    					{
    						HEAL
    						{
    							SOURCE PARENTSOURCE
    							TARGET PARENTTARGET
    							POWER COMBATANTPROPERTY ORIGINSOURCE POWER
    							DEFENSE 0
    							TAGS { Heal }
    						}
    					}
    				}
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Halver }
    		ADVANCEMENT 2
    		COST 2
    		EFFECTS
    		{
    			ATTACK
    			{
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { FIRST ENEMY }
    				POWER DIVIDE { LEFT COMBATANTPROPERTY TARGET HP RIGHT 2 }
    				DEFENSE 0
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Counter }
    		ADVANCEMENT 3
    		COST 0
    		EFFECTS
    		{
    			MAKENODE
    			{
    				SOURCE COMBATANT { CURRENT ACTOR }
    				DISTANCE 1
    				NODE
    				{
    					RULES
    					{
    						RULE
    						{
    							NAME { Pain For Pain! }
    							CRITERIA
    							{
    								CONTAINS TARGET PARENTSOURCE
    								TAGGED { Hurt }
    							}
    							OUTCOME REACT
    							EFFECT ATTACK
    							{
    								SOURCE ORIGINSOURCE
    								TARGET PARENTSOURCE
    								POWER COMBATANTPROPERTY SOURCE POWER
    								DEFENSE COMBATANTPROPERTY TARGET DEFENSE
    								NUMERATOR 3
    								DENOMINATOR 1
    							}
    						}
    					}
    				}
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Bleedify }
    		ADVANCEMENT 2
    		COST 0
    		EFFECTS
    		{
    			EMPTYATTACK
    			{
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { FIRST ENEMY }
    				POWER COMBATANTPROPERTY SOURCE POWER
    				DEFENSE COMBATANTPROPERTY TARGET DEFENSE
    				NUMERATOR 2
    				CONTINGENTEFFECTS
    				{
    					MAKENODE
    					{
    						SOURCE PARENTSOURCE
    						TARGET PARENTTARGET
    						DISTANCE 3
    						NODE
    						{
    							PASSED
    							RECURRENCEDISTANCE 3
    							RECURRENCECOUNT RESULT
    							EFFECTS
    							{
    								ATTACK
    								{
    									TARGET PARENTTARGET
    									POWER 1
    									DEFENSE 0
    								}
    							}
    						}
    					}
    				}
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { The Bomb }
    		ADVANCEMENT 4
    		COST 0
    		EFFECTS
    		{
    			MAKENODE
    			{
    				SOURCE COMBATANT { CURRENT ACTOR }
    				DISTANCE 10
    				NODE
    				{
    					PASSED
    					EFFECTS
    					{
    						ATTACK
    						{
    							SOURCE PARENTSOURCE
    							TARGET COMBATANT { ACTOR }
    							POWER COMBATANTPROPERTY ORIGINSOURCE POWER
    							NUMERATOR 5
    							DEFENSE COMBATANTPROPERTY TARGET DEFENSE
    						}
    					}
    				}
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Do All The Things }
    		ADVANCEMENT 10
    		COST 0
    		EFFECTS
    		{
    			MAKENODE
    			{
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { OTHER ALLY }
    				DISTANCE 1
    				NODE
    				{
    					RULES
    					{
    						RULE
    						{
    							CRITERIA
    							{
    								OVERLAPS SOURCE COMBATANT { ENEMY ACTOR }
    								CONTAINS TARGET COMBATANT { ALL ALLY OF ORIGINTARGET }
    								GREATERTHAN { LEFT COMBATANTPROPERTY ORIGINSOURCE POWER RIGHT 5 }
    								LESSTHAN { LEFT COMBATANTPROPERTY SOURCE DEFENSE RIGHT COMBATANTPROPERTY TARGET DEFENSE }
    								EQUAL { LEFT 9 RIGHT 9 }
    								ATLEAST { LEFT COMBATANTPROPERTY PARENTSOURCE HP RIGHT 10 }
    								ATMOST { LEFT RESULT RIGHT 6 }
    							}
    							OUTCOME FORBID
    						}
    					}
    				}
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Blast-through }
    		ADVANCEMENT 3
    		COST 2
    		EFFECTS
    		{
    			ATTACK
    			{
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { FIRST ENEMY }
    				POWER COMBATANTPROPERTY SOURCE POWER
    				DEFENSE COMBATANTPROPERTY TARGET DEFENSE
    				NUMERATOR 2
    				CONTINGENTEFFECTS
    				{
    					ATTACK
    					{
    						TARGET COMBATANT { SECOND ALLY OF PARENTTARGET }
    						POWER DIVIDE { LEFT RESULT RIGHT 2 }
    						DEFENSE 0
    					}
    				}
    			}
    		}
    	}
    	ACTION
    	{
    		NAME { Happy Dance }
    		ADVANCEMENT 3
    		COST 1
    		EFFECTS
    		{
    			GAINSP
    			{
    				SOURCE COMBATANT { CURRENT ACTOR }
    				TARGET COMBATANT { OTHER ALLY }
    				AMOUNT 1
    			}
    		}
    	}
    }
    

    TestEncounter2.txt -- describes one enemy party
    ENCOUNTER
    {
    	FATECHAIN
    	{
    		LINK
    		{
    			NODE
    			{
    				EFFECTS
    				{
    					HEAL
    					{
    						TARGET COMBATANT { CURRENT ACTOR }
    						POWER 1
    						DEFENSE 0
    						TAGS { Heal }
    					}
    				}
    			}
    		}
    		LINK
    		{
    			NODE
    			{
    				EFFECTS
    				{
    					GAINSP
    					{
    						TARGET COMBATANT { CURRENT ACTOR }
    						AMOUNT 1
    					}
    				}
    			}
    		}
    		LINK
    		{
    			NODE
    			{
    				RULES
    				{
    					RULE
    					{
    						NAME { Critical Hit }
    						OUTCOME MODIFY
    						CRITERIA
    						{
    							CONTAINS SOURCE COMBATANT { CURRENT ACTOR }
    							TAGGED { Hurt }
    						}
    						TRANSFORMATIONS
    						{
    							MULTIPLY 3
    						}
    					}
    				}
    			}
    		}
    		LINK
    		{
    			NODE
    			{
    				EFFECTS
    				{
    					GAINSP
    					{
    						TARGET COMBATANT { CURRENT ACTOR }
    						AMOUNT 1
    					}
    				}
    			}
    		}		
    		LINK
    		{
    			NODE
    			{
    				EFFECTS
    				{
    					GAINSP
    					{
    						TARGET COMBATANT { CURRENT ACTOR }
    						AMOUNT 1
    					}
    				}
    			}
    		}
    	}
    	TEAM
    	{
    		COMBATANTS
    		{
    			COMBATANT
    			{
    				NAME { Danny Cerr }
    				HP 40
    				POWER 4
    				DEFENSE 3
    			}
    			COMBATANT
    			{
    				NAME { Count Terror }
    				HP 40
    				POWER 3
    				DEFENSE 7
    			}
    			COMBATANT
    			{
    				NAME { Powerful Hans }
    				HP 40
    				POWER 7
    				DEFENSE 2
    			}
    		}
    		ACTIONS
    		{
    			COMBATANT
    			{
    				{ Power Up }
    				{ Happy Dance }
    			}
    			COMBATANT
    			{
    				{ Counter }
    				{ Revenge }
    			}
    			COMBATANT
    			{
    				{ Hurt Attack }
    				{ Halver }
    			}
    		}
    	}
    }
    

    After getting the core engine running, I came up against the idea of getting the AI to play the game again. Previously, I'd used a naive minimax search with Alpha-Beta pruning. Essentially, that means that the game performs a depth-first tree search, assigning each node a value as it goes. Leaf nodes get a heuristic value appraisal, while branch nodes get a value based on their children-- taking the minimum value of their children on the player's turn (because the player wants to defeat the computer) and taking the maximum value of their children on the computer's turn (because vice-versa). Alpha-Beta pruning relies on the antagonistic optimization behavior to avoid needlessly examining every node on the tree. In essence, each child is handed the current best and worst observed values from the parents, and can stop evaluating its own child nodes if it observes a value better or worse than the limits established by its parents. (I am butchering the explanation, but I don't think it's too far off the mark.) I set out to improve on my original implementation in a number of ways, and surprisingly... wound up back where I started.

    My first failed optimization was to retain the explored nodes in memory, using an actual tree structure rather than letting the search tree remain implicit in the recursion of the minimax function. The idea was that if you retained the nodes you'd searched, you could then very quickly search through any node you re-visited after the player took their turn. The problem with that strategy turned out to be those 1,073,741,824 total possible search states. Combined with the object pool code I used (I plan to use Unity as the engine, should I ever take this to a fully-realized game), I wound up keeping about 1.5 gigs of memory around in RAM. And it was all getting re-used, too! When you're trying to manage that much memory, you run into things like thrashing on memory caches. The performance went straight to hell, and I never actually observed a 10-depth search under that system to complete. The intermittent OutOfMemoryExceptions didn't help.

    So I looked up better options in minimax search. The next one I found was called NegaScout (actually Principal Variation Search, but c'mon... anything with "nega" in the title is inherent 347% cooler). The idea in NegaScout is to use an advance heuristic to try to guess which child of the current node is likeliest to be the principal variation-- that is, the best move. That node is explored first using typical the normal alpha-beta method, but with values of alpha and beta so close as to preclude adjustment-- essentially, doing nothing but verifying that the current node is, indeed, on the principal variation. If it fails, the search goes back up and starts over with a wider window. This strategy has been shown to explore no more nodes than simple Alpha-Beta pruning, while potentially arriving at the conclusion faster. However, I discovered that in practice, my NegaScout implementation actually took longer to resolve than my simple Alpha-Beta pruning function. Unless Chess (which is where NegaScout is most frequently applied), there really isn't a good move ordering for my game. You might think that moves that spend Skill Points tend to be better, but that's not always the case, especially when using your special move proximately results in stepping on a landmine and dying.

    Going beyond NegaScout, I also looked into-- though did not actually implement-- an algorithm called MTD(f). MTD(f) stands for something, and I am no longer confident what. MTD(f) is, as best as I understand it, binary search applied to minimax search. Rather than scan the entire depth for the best child value, MTD(f) instead starts with a best guess at the value of the node under test, then uses Alpha-Beta to determine if the node actually has that value. The return of Alpha-Beta will tell you whether you guessed correctly, or guessed wrong high or low. If you guess wrong, you adjust your guess and try again. However, this method turned out to be unfeasible for me as well. Part of the definition of the algorithm is that your Alpha-Beta implementation must save your searched nodes in memory in order to expedite the re-searching. And, well, see above. MTD(f) is predominantly focused on Chess, in which there are many ways to arrive at identical game states. In my game, almost no two game states are alike, so keeping the state in memory blows up, as I've described at length.

    So, instead, I went back to the solution I came to in the old rendition of this game: multithreading. By creating a basic thread pool, I was able to divide the analysis of each possible AI decision into its own thread. In practice, this reduced the run-time of the 10-depth search to something like 15 to 30 seconds, depending on the game state. It's absolutely not something that could be handled in a single frame. However, if the game takes some time to throw a lot of pretty animations around to display the results of the player's last choice, you could probably keep the player from spending too long in busy-wait for the next move.

    And that's where I am now. I've reached a point where I can't really add to the "game code" side of things any more, which means I kind of have to get off my ass and actually make a game around this engine rather than just lollygagging around in the land of pure theory. What a horrible position, am I right? :lol:

    Kupi on
    My favorite musical instrument is the air-raid siren.
  • Options
    GarthorGarthor Registered User regular
    Delzhand wrote: »
    At the moment it's that C++ devs seem incapable of choosing good variable names. The larger issue is that I can't figure out how to convert unreal's FString to a format that can be split by strtok.

    I think UE4 REALLY wants you to use their FString (and TCHAR) classes/structs, probably because string handling gets REALLY OBNOXIOUS when you start doing certain localizations. If all you're trying to do is tokenize a string then you can just use ParseIntoArray on the FString. If you NEED a c-string, then the TCHAR_TO_ANSI(str) should convert it for you.

  • Options
    KhavallKhavall British ColumbiaRegistered User regular
    edited November 2015
    I don't know what it is that makes me completely seize up when using C++, because I actually have if anything more experience with c++ than I do with c#, but I'm like a million times faster with c#, feel better while using it, debug better with it(or at least find alternate ways of achieving the same effect).

    Which ends up being just fine, because right now I need to be able to export to lower-performance machines, which Unity seems much better at, and also Wwise with Unity is basically automatic, and Wwise with Unreal is a nightmare of epic proportions that makes me have everything that has ever existed.

    The only problem is that I'm not practicing my c++ if I need to use Max/MSP(to make my own externals, since I hate Max/MSP), but even my supervisor who is incredibly well-known for his Max/MSP work with generative music admits that if I have alternate for Max/MSP, it's probably best to just use that instead anyways.

    Khavall on
  • Options
    DelzhandDelzhand Hard to miss. Registered User regular
    Garthor wrote: »
    Delzhand wrote: »
    At the moment it's that C++ devs seem incapable of choosing good variable names. The larger issue is that I can't figure out how to convert unreal's FString to a format that can be split by strtok.

    I think UE4 REALLY wants you to use their FString (and TCHAR) classes/structs, probably because string handling gets REALLY OBNOXIOUS when you start doing certain localizations. If all you're trying to do is tokenize a string then you can just use ParseIntoArray on the FString. If you NEED a c-string, then the TCHAR_TO_ANSI(str) should convert it for you.

    Yeah, I found ParseIntoArray, finally. When I see a documentation page like this https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/StringHandling/FString/index.html#stringvariables I instinctively look at the tables on the page to see what options I've got. ParseIntoArray is mentioned in a paragraph, so I totally missed it.

    I very specifically do not want to get into the weeds of string handling, so this is perfect. All I wanted to do was convert a string like "camera_set_tf 10 -160 230 0 -10 144" into its component pieces.

  • Options
    PhyphorPhyphor Building Planet Busters Tasting FruitRegistered User regular
    edited November 2015
    Delzhand wrote: »
    At the moment it's that C++ devs seem incapable of choosing good variable names. The larger issue is that I can't figure out how to convert unreal's FString to a format that can be split by strtok.

    There are macros to convert. WCHAR_TO_UTF8 I think?

    Phyphor on
  • Options
    HandkorHandkor Registered User regular
    I used to be a C++ dev almost a decade ago and then started working in C# and I love it. I've recently fell back into C++ with UE4 and it feels so foreign. Slowly getting used to the way UE4 does things but I am glad they have a managed layer for memory objects.

    In other news I've put up Omnitron, my winning entry to Epic Megajam up on Steam Greenlight (click my sig for link). Now over the next couple of months I will take this game from jam entry to a fleshed out game.

    I have to say though that preparing a bunch of marketing stuff is harder than making the actual game. Took me over a week to come up with a studio name and logo.

  • Options
    TofystedethTofystedeth Registered User regular
    Anybody know of some good non video tutorials for Unity 5.2 2D stuff?
    I tried a tute that was written for 5.0 and in the first 30 seconds I hit a difference I couldn't figure out.

    steam_sig.png
  • Options
    DelzhandDelzhand Hard to miss. Registered User regular
    I'm getting over the humps of C++ development pretty quickly, but there are still things I don't like. Intellisense in C# is lightning fast, with C++ I'm better of switching to chrome and googling.

    On the plus side, I've figured out how to create my own GameMode that allows me to enter console commands which create data I can pick up in blueprints. My first working example is
    ScenarioAddAction CameraSetTfLerp 200,100,300/0,45,0/1,1,1 2
    

    Which causes the camera to move/rotate/scale over a given time. I'm hoping to make it so absolutely everything that can happen in the game, from damage popup text to setting a unit's waypoints, to starting attack animations/visual effects, can be initiated through the console. This will allow me to handle cutscenes and gameplay with the same logic, and make it easy to write text scenarios where anything available in combat is available for cinematics.

  • Options
    GlalGlal AiredaleRegistered User regular
    If anyone is shopping around for a light-weight sprite animation tool, Spriter Pro is currently on sale on Bundle Stars. It has a free version you can download off their official site if you want to give it a spin first, though it lacks IK bone locking and some other more advanced features that the paid version comes with.

  • Options
    KashaarKashaar Low OrbitRegistered User regular
    Delzhand wrote: »
    I'm getting over the humps of C++ development pretty quickly, but there are still things I don't like. Intellisense in C# is lightning fast, with C++ I'm better of switching to chrome and googling.

    On the plus side, I've figured out how to create my own GameMode that allows me to enter console commands which create data I can pick up in blueprints. My first working example is
    ScenarioAddAction CameraSetTfLerp 200,100,300/0,45,0/1,1,1 2
    

    Which causes the camera to move/rotate/scale over a given time. I'm hoping to make it so absolutely everything that can happen in the game, from damage popup text to setting a unit's waypoints, to starting attack animations/visual effects, can be initiated through the console. This will allow me to handle cutscenes and gameplay with the same logic, and make it easy to write text scenarios where anything available in combat is available for cinematics.

    You're right on switching off IntelliSense, but instead of Googling, use Visual Assist. It's pretty awesome! I'm currently on a trial, and pretty sure I'll shell out for it when that's through.

    Indie Dev Blog | Twitter | Steam
    Unreal Engine 4 Developers Community.

    I'm working on a cute little video game! Here's a link for you.
  • Options
    GlalGlal AiredaleRegistered User regular
    I've a question about UE4- I'm thinking of having a portrait system where the head and facial features are on separate layers, so I don't have to create art for all the possible combinations of both.
    The easiest way to have them line up would be to have them all be the same size and just overlay them (as the source already has them on separate, lined-up layers), however I worry that having things like eyes be an image as big as the full portrait will unnecessarily waste memory.

    If I have an image that's mostly just fully transparent alpha with a visible bit in the middle, is the engine smart enough to not have the alpha waste memory, or will it eat up as much memory as a complex image would? Images are generally stored uncompressed in memory when loaded up (which means X pixels is X pixels regardless of run-length encoding), but is that also true in game engines/UE4 or is there fancy back-end work to reduce that load?

    I could, of course, just store them cropped, but that means then aligning them in-engine, while will be a huge pain if I ever want to alter the original artwork dimensions. Plus, I'd have to align each variant individually, which is blergh.

  • Options
    LaCabraLaCabra MelbourneRegistered User regular
    I can't really answer your question because I don't know enough low level engine stuff, but can tell you there's almost certainly not enough of a potential saving for that to actually be worth optimising for

  • Options
    MachwingMachwing It looks like a harmless old computer, doesn't it? Left in this cave to rot ... or to flower!Registered User regular
    If you're really worried about the performance cost, I'd consider storing them cropped and aligning in-engine. You shouldn't be worried unless you're going to have a ton of these portraits loaded in memory simultaneously, though. The renderer's smart enough to short-circuit on pixels with zero alpha so it's a trivial additional cost on-screen.

    Texture atlasing is perfect for this sort of thing though, I deffo recommend using it

    l3icwZV.png
  • Options
    GlalGlal AiredaleRegistered User regular
    edited November 2015
    Cheers! I'll just make a non-cropped sprite atlas then, by far the easiest.

    Glal on
  • Options
    DelzhandDelzhand Hard to miss. Registered User regular
    edited November 2015
    I just came here to complain about spending 7 hours trying to get something to work in Unreal and as I was typing it I had the idea to try something that failed early on, but in a different context.

    It worked, cutting out a 30-node blueprint chain

    the game development gods are fickle

    edit: on a side note, I've become hopelessly addicted to making my blueprints look good with reroute nodes

    Delzhand on
  • Options
    LaCabraLaCabra MelbourneRegistered User regular
    edited May 2022
    I am the reroute node God.
    22464675898_a42189168f_o.png

    LaCabra on
  • Options
    MahnmutMahnmut Registered User regular
    Kashaar wrote: »
    Delzhand wrote: »
    I'm getting over the humps of C++ development pretty quickly, but there are still things I don't like. Intellisense in C# is lightning fast, with C++ I'm better of switching to chrome and googling.

    On the plus side, I've figured out how to create my own GameMode that allows me to enter console commands which create data I can pick up in blueprints. My first working example is
    ScenarioAddAction CameraSetTfLerp 200,100,300/0,45,0/1,1,1 2
    

    Which causes the camera to move/rotate/scale over a given time. I'm hoping to make it so absolutely everything that can happen in the game, from damage popup text to setting a unit's waypoints, to starting attack animations/visual effects, can be initiated through the console. This will allow me to handle cutscenes and gameplay with the same logic, and make it easy to write text scenarios where anything available in combat is available for cinematics.

    You're right on switching off IntelliSense, but instead of Googling, use Visual Assist. It's pretty awesome! I'm currently on a trial, and pretty sure I'll shell out for it when that's through.

    Yeah, VA's faster intellisense is pretty crucial when you're in a large C++ code base like Unreal.

    Steam/LoL: Jericho89
  • Options
    LaCabraLaCabra MelbourneRegistered User regular
    So I mentioned HammUEr in here before, right? I just did a video about it. Coming Soon!

    https://www.youtube.com/watch?v=rJzguNJsivM&feature=youtu.be

    Also ported a Half-Life level to UE4

  • Options
    IncenjucarIncenjucar VChatter Seattle, WARegistered User regular
    So with Unity I'm running into the issue of movement happening too fast for the physics to handle, causing things moving fast enough to phase through objects. Is there a specific speed limit that prevents this issue? Does anyone doing anything that isn't slow end up having to use one of the fifty trucks suggested online to force physics to push back?

  • Options
    LaCabraLaCabra MelbourneRegistered User regular
    Haven't got a unity solution so this is probably not useful but on Unreal that problem exists and is solvable by physics substepping and enabling something called Continuous Collision Detection

  • Options
    GlalGlal AiredaleRegistered User regular
    This particular solution only works for small objects (at least without multiple casts), but seems elegant.
    http://answers.unity3d.com/questions/587586/unity-high-speed-collision-detect.html

  • Options
    LorkLork Registered User regular
    edited November 2015
    Incenjucar wrote: »
    So with Unity I'm running into the issue of movement happening too fast for the physics to handle, causing things moving fast enough to phase through objects. Is there a specific speed limit that prevents this issue? Does anyone doing anything that isn't slow end up having to use one of the fifty trucks suggested online to force physics to push back?
    How are you moving the object? Are you setting its position manually or using physics forces? Are you moving it in FixedUpdate() or Update()? If you are doing all that in the correct fashion (applying forces to the rigidbody in FixedUpdate) and it's still happening, you can try setting collision detection in the relevant object's rigidbody to continuous dynamic. You can also try increasing the physics tick rate by lowering the values of the Fixed Timestep and and Maximum Allowed Timestep in Project Settings -> Time. The default value is something like 30/sec which I find to be dangerously slow.

    Lork on
    Steam Profile: Lork
  • Options
    MahnmutMahnmut Registered User regular
    Incenjucar wrote: »
    So with Unity I'm running into the issue of movement happening too fast for the physics to handle, causing things moving fast enough to phase through objects. Is there a specific speed limit that prevents this issue? Does anyone doing anything that isn't slow end up having to use one of the fifty trucks suggested online to force physics to push back?

    The speed limit is roughly (distance to jump the collision volume) / time of your physics step. So you can also try making the objects bigger. :P

    Steam/LoL: Jericho89
  • Options
    KashaarKashaar Low OrbitRegistered User regular
    LaCabra wrote: »
    I am the reroute node God. You shall kneel
    22464675898_a42189168f_o.png

    So are we doing this then, huh?
    ue4-bpwires1.jpg

    ue4-bpwires4.jpg

    ue4-bpwires5.jpg

    Indie Dev Blog | Twitter | Steam
    Unreal Engine 4 Developers Community.

    I'm working on a cute little video game! Here's a link for you.
  • Options
    HandkorHandkor Registered User regular
    Kashaar wrote: »
    LaCabra wrote: »
    I am the reroute node God. You shall kneel
    22464675898_a42189168f_o.png

    So are we doing this then, huh?
    ue4-bpwires1.jpg

    ue4-bpwires4.jpg

    ue4-bpwires5.jpg

    I will not shame myself but I do underuse the reroute nodes.

  • Options
    TofystedethTofystedeth Registered User regular
    Glal wrote: »
    I've a question about UE4- I'm thinking of having a portrait system where the head and facial features are on separate layers, so I don't have to create art for all the possible combinations of both.
    The easiest way to have them line up would be to have them all be the same size and just overlay them (as the source already has them on separate, lined-up layers), however I worry that having things like eyes be an image as big as the full portrait will unnecessarily waste memory.

    If I have an image that's mostly just fully transparent alpha with a visible bit in the middle, is the engine smart enough to not have the alpha waste memory, or will it eat up as much memory as a complex image would? Images are generally stored uncompressed in memory when loaded up (which means X pixels is X pixels regardless of run-length encoding), but is that also true in game engines/UE4 or is there fancy back-end work to reduce that load?

    I could, of course, just store them cropped, but that means then aligning them in-engine, while will be a huge pain if I ever want to alter the original artwork dimensions. Plus, I'd have to align each variant individually, which is blergh.

    On the plus side, you could animate eyebrow wagging.

    steam_sig.png
  • Options
    l_gl_g Registered User regular
    edited November 2015
    Incenjucar wrote: »
    So with Unity I'm running into the issue of movement happening too fast for the physics to handle, causing things moving fast enough to phase through objects. Is there a specific speed limit that prevents this issue? Does anyone doing anything that isn't slow end up having to use one of the fifty trucks suggested online to force physics to push back?

    The first question you may want to ask yourself is "should these things be moving this fast in the first place?"

    If the answer to that question is "yes", then you'll have a bunch of possible questions/solutions:
    - set the Physics collision testing to "continuous". This is a poor solution if you will have a large number of these objects (e.g. if you're aiming for a Battlefield-esque scenario where 64 players are spraying the sky with guns that fire 60 rounds/sec, your performance will suffer dearly)

    - if it's regularly going that fast, do you even want regular physics to run on it? Consider that something moving that fast, with rigid body physics on it, is going to deflect off things it hits with similar speed or will impart huge momentum to anything that it hits. You may want to use a raycast/spherecast/capsulecast based approach, even if the thing you are firing is not an actual ray. For instance, you can raycast a limited distance in front of the subject every update, with the distance scaling depending on the speed of the subject.

    - what is the physics framerate? You can configure the size of the timestep for more frequent updates, but this does have performance implications.

    l_g on
    Cole's Law: "Thinly sliced cabbage."
  • Options
    KhavallKhavall British ColumbiaRegistered User regular
    Also, it seems obvious, but your Physics code is in FixedUpdate() and not Update(), right?

    It's a little thing, but Update can have wonky effects, especially with fast-moving things.

  • Options
    AnarchyAnarchy Registered User regular
    Khavall wrote: »
    Also, it seems obvious, but your Physics code is in FixedUpdate() and not Update(), right?

    It's a little thing, but Update can have wonky effects, especially with fast-moving things.

    +1 on this. I'm having to rewrite a good portion of my own game for this very reason.

    "Oh, well, this would be one of those circumstances that people unfamiliar with the law of large numbers would call a coincidence."
  • Options
    MorninglordMorninglord I'm tired of being Batman, so today I'll be Owl.Registered User regular
    edited November 2015
    Khavall wrote: »
    Also, it seems obvious, but your Physics code is in FixedUpdate() and not Update(), right?

    It's a little thing, but Update can have wonky effects, especially with fast-moving things.

    This feels like something I'll be having problems with when I come to work on my combat. I like things fast.

    I was actually wondering, how hard is it to create rigid feedback states for enemies using unity physics? I wanted, eg, every upwards juggle strike to always launch at the same height, with the same float at the top, and the same fall speed, unless interacted with. Or every knockback to do the same angle and stuff. Is this easy to do? Prediction is pretty important to me.
    Which engine is better at doing customised stuff like this? Would I be better off with UE4?

    Morninglord on
    (PSN: Morninglord) (Steam: Morninglord) (WiiU: Morninglord22) I like to record and toss up a lot of random gaming videos here.
  • Options
    KhavallKhavall British ColumbiaRegistered User regular
    Khavall wrote: »
    Also, it seems obvious, but your Physics code is in FixedUpdate() and not Update(), right?

    It's a little thing, but Update can have wonky effects, especially with fast-moving things.

    This feels like something I'll be having problems with when I come to work on my combat. I like things fast.

    I was actually wondering, how hard is it to create rigid feedback states for enemies using unity physics? I wanted, eg, every upwards juggle strike to always launch at the same height, with the same float at the top, and the same fall speed, unless interacted with. Or every knockback to do the same angle and stuff. Is this easy to do? Prediction is pretty important to me.
    Which engine is better at doing customised stuff like this? Would I be better off with UE4?

    The important thing to remember about the difference between the two is that FixedUpdate() is called at a specific rate, and Update() is called when the frame refreshes. So in general physics code should go into FixedUpdate because otherwise a frame hiccup can cause some... unintended consequences(for instance, an object suddenly going half the expected speed because it moved the same amount each call, but the calls were at half the rate).

    Similarly, you can alleviate this by multiplying by Time.deltaTime if you've got something you for some reason don't want to cram into FixedUpdate(which can happen). Time.deltaTime is the time it took to draw the frame, so multiplying by it scales the movement to the frame lag.


    For the other thing, if you want consistency and don't need physics, it's probably a good idea to use custom movement instead of physics movement. Physics can be fickle for consistency. Luckily, custom movement is really not that difficult. Both UE4 and Unity have a physics-based and non-physics-based character controllers, so you don't have to worry about one engine being better at it than the other.

    I mean I've gotten into the habit of using charactercontrollers over rigidbodies for almost everything I do, unless I have a compelling need for physics(or for some reason I want something to, like, hit a bunch of boxes. Which... I don't. I never have something like that)

  • Options
    DelzhandDelzhand Hard to miss. Registered User regular
    For the life of me I cannot get character movement to work like I want. I started off with Simple Move to Location, which causes the character to get close to the destination, but stop short. Move to Location with Acceptance Radius .1 isn't noticeably closer.

    I suspect it has to do with the collision capsule and overlap events. But the problem is that I want my character's feet (the bottom of the capsule) touching the exact point. I can't move the capsule component because it's inherited. And I know I could override the character class to change it, but that's clearly not the "intended usage" in UE.

    I tried making the capsule radius 0, which caused my character to slide off a slope into the void. But even when I tried it on flat ground, it caused the character to jitter like fuck and both Move variants to do nothing.

    I also tried using a Timeline to lerp between the start and origin, which does get me to the right spot, but doesn't register as velocity and thus the character doesn't animate or turn. Obviously sliding around like chess pieces isn't going to work, but this feels closer to how I want things to work. I managed to get this all working in Unity without anything like a navmesh, but I'd like to leverage the engine's strengths if I can.

    Also, maybe I'm missing something, but Unreal doesn't seem to have blueprint accessible queues or stacks?

  • Options
    MorninglordMorninglord I'm tired of being Batman, so today I'll be Owl.Registered User regular
    edited November 2015
    Khavall wrote: »
    Khavall wrote: »
    Also, it seems obvious, but your Physics code is in FixedUpdate() and not Update(), right?

    It's a little thing, but Update can have wonky effects, especially with fast-moving things.

    This feels like something I'll be having problems with when I come to work on my combat. I like things fast.

    I was actually wondering, how hard is it to create rigid feedback states for enemies using unity physics? I wanted, eg, every upwards juggle strike to always launch at the same height, with the same float at the top, and the same fall speed, unless interacted with. Or every knockback to do the same angle and stuff. Is this easy to do? Prediction is pretty important to me.
    Which engine is better at doing customised stuff like this? Would I be better off with UE4?

    The important thing to remember about the difference between the two is that FixedUpdate() is called at a specific rate, and Update() is called when the frame refreshes. So in general physics code should go into FixedUpdate because otherwise a frame hiccup can cause some... unintended consequences(for instance, an object suddenly going half the expected speed because it moved the same amount each call, but the calls were at half the rate).

    Similarly, you can alleviate this by multiplying by Time.deltaTime if you've got something you for some reason don't want to cram into FixedUpdate(which can happen). Time.deltaTime is the time it took to draw the frame, so multiplying by it scales the movement to the frame lag.


    For the other thing, if you want consistency and don't need physics, it's probably a good idea to use custom movement instead of physics movement. Physics can be fickle for consistency. Luckily, custom movement is really not that difficult. Both UE4 and Unity have a physics-based and non-physics-based character controllers, so you don't have to worry about one engine being better at it than the other.

    I mean I've gotten into the habit of using charactercontrollers over rigidbodies for almost everything I do, unless I have a compelling need for physics(or for some reason I want something to, like, hit a bunch of boxes. Which... I don't. I never have something like that)

    I'll probably go with custom movement then. I want absolute control over the interactions between entities.

    Morninglord on
    (PSN: Morninglord) (Steam: Morninglord) (WiiU: Morninglord22) I like to record and toss up a lot of random gaming videos here.
  • Options
    l_gl_g Registered User regular
    If rigid body behaviour is not a desired aspect of your gameplay, then don't enable rigid body behaviour by making use of the kinematic flag.

    Unity's standard is to use the rigid body component for collision detection, even if rigid body physical behaviour is not desired. You can absolutely script the behaviour on collision as you want. Also, nothing stops you from not using the rigid body component at all for your collision detection and writing all your own, but in a fully-3D environment not having to have to code this yourself is convenient. Efficient collision detection for lots of 3D objects in 3D space is a non-trivial problem.

    Cole's Law: "Thinly sliced cabbage."
  • Options
    KhavallKhavall British ColumbiaRegistered User regular
    edited November 2015
    Unity doesn't use the Collider component for collision detection?

    EDIT: The unity API literally says "The Character Controller is mainly used for third-person or first-person player control that does not make use of Rigidbody physics." If you're going to have the character interact with other rigid bodies, or want it to have the ability to just turn on physics, then RigidBody is best with isKinematic turned off by default, but you don't have to custom-script collision entirely if you don't use a RigidBody, that would be insane.

    Khavall on
  • Options
    l_gl_g Registered User regular
    Khavall wrote: »
    Unity doesn't use the Collider component for collision detection?

    It depends. If your only source of collisions is, say, raycasts, and your objects in the scene aren't moving, then that's perfectly valid. If you have moving objects that have Colliders on them but not rigid body components, the collision detection behaves wonkily. At least, that's how it used to be. It might not be that way anymore! Do tell me if that is the case!

    Cole's Law: "Thinly sliced cabbage."
  • Options
    MorninglordMorninglord I'm tired of being Batman, so today I'll be Owl.Registered User regular
    edited November 2015
    I'm not interested in having knocked back enemies hit other enemies. The only collision that needs to be coded in terms of knock back is player<->enemy and enemy<->environment.
    The only problem I can forsee is if I have a lot of enemies, and they all get hit at the same time, that might slow things down a lot if its done inefficiently. So I'm looking into the most efficient method of doing this that gets me the most control.
    This doesn't sound like a design I need physics simulation for, since that would basically involve unnecessary calculations.

    Morninglord on
    (PSN: Morninglord) (Steam: Morninglord) (WiiU: Morninglord22) I like to record and toss up a lot of random gaming videos here.
  • Options
    KhavallKhavall British ColumbiaRegistered User regular
    edited November 2015
    l_g wrote: »
    Khavall wrote: »
    Unity doesn't use the Collider component for collision detection?

    It depends. If your only source of collisions is, say, raycasts, and your objects in the scene aren't moving, then that's perfectly valid. If you have moving objects that have Colliders on them but not rigid body components, the collision detection behaves wonkily. At least, that's how it used to be. It might not be that way anymore! Do tell me if that is the case!

    I've had a lot of practice with non-physics-y stuff personally, because I have very strict timings that I need objects to obey, and so can't really use physics in any way, and I've never had a problem with collision detection. Worst case scenario is I'll have objects run into each other and just sort of slide around each other unrealistically, but whatever... I'm not using physics anyways.

    Basically the way it works now with what I'm doing is if I'm just having everything that moves need to move without physics, I've never had a problem using only charactercontrollers and completely ignoring RigidBodies. Now, if I want anything with physics, then any object that I want to interact with those physics objects to have a RigidBody, but I would only really use physics for non-game-centric showy stuff, so.. I just forget about them mostly.


    Now I will say that if I had a bunch of objects running into each other at the same time then, yeah that would probably get pretty wonky pretty quickly. But then again, if I was using something like a Vector3.MoveTowards and 4 objects ran into each other and tried to push through each other with physics then they would still probably get wonky pretty quickly.

    Khavall on
Sign In or Register to comment.