{"author_link":"\/users\/tonho","author_name":"Tonho","author_uid":"tonho","comments":[],"epoch":1571764743,"event":"LD45","format":"md","ldjam_node_id":176186,"likes":14,"metadata":{"p_key":"137459","p_author":"Tonho","p_authorkey":"1125603","p_urlkey":"353735","p_title":"\u30d0\u30af\u30e9\u30a6Bloodless | Reusable Code ","p_cat":"LDJam ","p_event":"LD45","p_time":"1571764743","p_likes":"14","p_comments":"0","p_status":"WAYBACK","us_key":"1125603","us_name":"Tonho","us_username":"tonho","event_start":"1570147200","event_key":"78","event_name":"Ludum Dare 45"},"node":{"_collation":{"body_sanitizer":"TextUtils::SanitizeHTML via existing importer","event":"LD45","removed_author":false},"_superparent":159347,"_trust":1,"author":125603,"body":"Hey folks. Hope you're having fun with all the games! I wanted to share a bit about our development process for [\u30d0\u30af\u30e9\u30a6Bloodless](https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless), specially code stuff. Here ya go!\n\n![LV03-3Enemies.gif](\/\/\/raw\/3aa\/e1\/z\/29c84.gif)\n\nI thought it would be cool to go over the libraries we used, as well as the modules we developed during the jam. I want to tidy up the stuff we built as separate git projects so anyone can use\/contribute to them, but for now they\u2019re all in the(not too tidy) [jam repo](https:\/\/github.com\/AntonioHR\/LD45). Let's go over all this stuff\n\n## 3rd Party stuff\n\n### Unity\nI guess I should include this, right? We used Unity 2019.2 . One weird thing about Unity is that it often requires you to build your own systems for stuff like audio,  because it's basic audio system is weird. More on that later!\n\n### DOTween\nFor those who don't know DOTween, it's an amazing and easy to use code-driven animation library with a free version. Ever since I've known DOTween, I don't think I've ever had a project where I didn't use it. It's also especially great for jams because of how it allows for a lot of complex behaviours to be implemented super quickly by code, and it allows you to make all of that stuff be event-driven, which I found often leads to better code!\n\n## Code from previous projects\nWe used some code from previous projects, with tweaks to some of them\n\n### State Machines\n\nState Machines are super  useful([here's a really good text about them if you don\u2019t know them](https:\/\/gameprogrammingpatterns.com\/state.html) )! I really like our specific implementation. It's pretty straightforward. Here\u2019s what one of its states looks like\n```\npublic class IdleState : PlayerStateBase\n    {\n \n        protected override void Begin()\n        {\n \n        }\n        public override void FixedUpdate()\n        {\n            Player.defaultMover.DoFixedUpdate(Player, Player.DirectionInput);\n        }\n        public override void OnDashPressed()\n        {\n            ExitTo(new DashState(Player.FacingDirection));\n        }\n \n    }\n```\nAnd the base class for player states looks like this\n```\n public class PlayerStateBase : State<PlayerController, PlayerStateBase>\n    {\n        protected PlayerController Player { get => Context; }\n \n        public virtual void Update() { }\n        public virtual void FixedUpdate() { }\n \n        public virtual void OnDashPressed() { }\n \n        public virtual void OnNoHealth()\n        {\n            ExitTo(new DeadState());\n        }\n...\n```\nOne nice thing about how we implemented the state machines is that it doesn't allow you to change, or even access states from outside. This leads you to isolate the state machine logic and communicate through events, which I find to be a good way to make the machine cleaner and easier to debug.\n\n\n### Character Movement\nWe used a rigidbody-based top-down movement code we had from previous projects. The movement is pretty simple, just a few weird forces that made the movement feel right to me, especially when changing direction. What I really liked was how the movement class is structured:\n\nYou create and configure a mover as following. Think of these as movements presets\n![pasted image 0.png](\/\/\/raw\/3aa\/e1\/z\/29c87.png)\nThen you Implement a simple interface\n```\npublic interface IMovingChar\n{\n  public Rigibody2D Rigidbody { get; }\n  public Vector2 FacingDirection { get; }\n}\n```\nAnd you just call the mover every frame\n```\n   mover.DoFixedUpdate(this, input);\n```\n\nThis makes it really easy to change the movement style of characters in different modes. We used this a lot with enemies to tweak their walk and attack movement speeds\n\n### Object Triggers\n\nBecause it's really common for you to have objects that trigger when they collide with an object of a specific type, we had code from previous projects for easy object triggers. You use it by extending this ObjectTrigger<T> generic class and implement the OnTriggered  function:\n\n```\npublic class SimpleHazard : ObjectTrigger<PlayerController>\n{\n  protected override void OnTrigger(PlayerController player)\n  {\n    player.OnHit(transform);\n  }\n}\n```\nThere's also this functionality with the triggers where you can create \"proxies\", so that you can add \"external\" hitboxes that are detected as the class they proxy for. I really want to use this one day for a boss where it just has lots of spots where you can hit!!!\n\n```\npublic class PlayerExtraHitbox: IProxyFor<PlayerController>\n{\n  [SerializeField]\n  private PlayerController player;\n  \n  public PlayerController Owner { get { return owner; } }\n}\n```\n\n## Jam Made Systems\n### Audio\nI always have a hard time using unity's audio system. I just find it super hard to do even simple behaviours with it, and there are a lot of recurring problems, like a sound effect increasing in sound if it's triggered multiple times in the same frame. For all of those reasons, this jam I finally built a little sound system. It's far from perfect, and not very optimized for a big scale game, but it worked pretty well for the jam!\n\nHere's how it\u2019s used:\nFor each individual sound effect in the game, you create a sound effect asset like this. You can configure some stuff in it like what audiomixer group it outputs to, and a minimum play interval so you can stop it from triggering multiple times in a frame\n![unnamed.png](\/\/\/raw\/3aa\/e1\/z\/29c8b.png)\nThen you add it to the audio database\n![db.png](\/\/\/raw\/3aa\/e1\/z\/29c8c.png)\nAnd you can play it in your game either by id or by the asset reference\n\n```\n   AudioManager.Instance.Play(\"transition_end\");\n```\nThen in the game it just creates the needed audiosources\n![audioplayers.png](\/\/\/raw\/3aa\/e1\/z\/29c8d.png)\n\n### Events\n\nWe built a nice event system for this game. It uses strings for event ids. I was a bit skeptical about using a system with strings for the events instead of just adding c# events to the each of the game's modules. In the end, I really liked how the string events allowed you to build stuff just through the inspector. I guess in the end both c# events and string-based events can coexist  serving different functions!\n\n\n```\n   TriggerManager.StartListening(EventName.OnBossSpawn, OnBossSpawn);\n```\n\n\n## Final Thoughts\nSo those are the systems we used for building our game. Again, the whole code is available at the [project\u2019s repo on GitHub](https:\/\/github.com\/AntonioHR\/LD45), so if you think any of these could be helpful, feel free to use them! \n\nFor more on our jam process, here's some other posts by our team, as well as our game\n\n[Level Design](https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless\/bloodless-level-design-process)\n\n[Sound Design](https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless\/bloodless-sound-design-process)\n\n[\u30d0\u30af\u30e9\u30a6 Bloodless](https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless)\n","comments":0,"created":"2019-10-22T16:52:57Z","files":[],"files-timestamp":0,"id":176186,"love":14,"love-timestamp":"2019-10-23T06:40:33Z","meta":[],"modified":"2019-10-23T06:40:33Z","name":"\u30d0\u30af\u30e9\u30a6Bloodless | Reusable Code ","node-timestamp":"2019-10-22T18:17:44Z","parent":170129,"parents":[1,5,9,159347,170129],"path":"\/events\/ludum-dare\/45\/bloodless\/bloodless-reusable-code","published":"2019-10-22T17:19:03Z","scope":"public","slug":"bloodless-reusable-code","subsubtype":"","subtype":"","type":"post","version":531737},"node_metadata":{"n_key":"176186","n_urlkey":"353735","n_parent":"170129","n_path":"\/events\/ludum-dare\/45\/bloodless\/bloodless-reusable-code","n_slug":"bloodless-reusable-code","n_type":"post","n_subtype":"","n_subsubtype":"","n_author":"125603","n_created":"1571763177","n_modified":"1571812833","n_version":"531737","n_status":"WAYBACK"},"source_url":"https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless\/bloodless-reusable-code","text":"Hey folks. Hope you're having fun with all the games! I wanted to share a bit about our development process for [\u30d0\u30af\u30e9\u30a6Bloodless](https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless), specially code stuff. Here ya go!\n\n![LV03-3Enemies.gif](\/\/\/raw\/3aa\/e1\/z\/29c84.gif)\n\nI thought it would be cool to go over the libraries we used, as well as the modules we developed during the jam. I want to tidy up the stuff we built as separate git projects so anyone can use\/contribute to them, but for now they\u2019re all in the(not too tidy) [jam repo](https:\/\/github.com\/AntonioHR\/LD45). Let's go over all this stuff\n\n## 3rd Party stuff\n\n### Unity\nI guess I should include this, right? We used Unity 2019.2 . One weird thing about Unity is that it often requires you to build your own systems for stuff like audio,  because it's basic audio system is weird. More on that later!\n\n### DOTween\nFor those who don't know DOTween, it's an amazing and easy to use code-driven animation library with a free version. Ever since I've known DOTween, I don't think I've ever had a project where I didn't use it. It's also especially great for jams because of how it allows for a lot of complex behaviours to be implemented super quickly by code, and it allows you to make all of that stuff be event-driven, which I found often leads to better code!\n\n## Code from previous projects\nWe used some code from previous projects, with tweaks to some of them\n\n### State Machines\n\nState Machines are super  useful([here's a really good text about them if you don\u2019t know them](https:\/\/gameprogrammingpatterns.com\/state.html) )! I really like our specific implementation. It's pretty straightforward. Here\u2019s what one of its states looks like\n```\npublic class IdleState : PlayerStateBase\n    {\n \n        protected override void Begin()\n        {\n \n        }\n        public override void FixedUpdate()\n        {\n            Player.defaultMover.DoFixedUpdate(Player, Player.DirectionInput);\n        }\n        public override void OnDashPressed()\n        {\n            ExitTo(new DashState(Player.FacingDirection));\n        }\n \n    }\n```\nAnd the base class for player states looks like this\n```\n public class PlayerStateBase : State<PlayerController, PlayerStateBase>\n    {\n        protected PlayerController Player { get => Context; }\n \n        public virtual void Update() { }\n        public virtual void FixedUpdate() { }\n \n        public virtual void OnDashPressed() { }\n \n        public virtual void OnNoHealth()\n        {\n            ExitTo(new DeadState());\n        }\n...\n```\nOne nice thing about how we implemented the state machines is that it doesn't allow you to change, or even access states from outside. This leads you to isolate the state machine logic and communicate through events, which I find to be a good way to make the machine cleaner and easier to debug.\n\n\n### Character Movement\nWe used a rigidbody-based top-down movement code we had from previous projects. The movement is pretty simple, just a few weird forces that made the movement feel right to me, especially when changing direction. What I really liked was how the movement class is structured:\n\nYou create and configure a mover as following. Think of these as movements presets\n![pasted image 0.png](\/\/\/raw\/3aa\/e1\/z\/29c87.png)\nThen you Implement a simple interface\n```\npublic interface IMovingChar\n{\n  public Rigibody2D Rigidbody { get; }\n  public Vector2 FacingDirection { get; }\n}\n```\nAnd you just call the mover every frame\n```\n   mover.DoFixedUpdate(this, input);\n```\n\nThis makes it really easy to change the movement style of characters in different modes. We used this a lot with enemies to tweak their walk and attack movement speeds\n\n### Object Triggers\n\nBecause it's really common for you to have objects that trigger when they collide with an object of a specific type, we had code from previous projects for easy object triggers. You use it by extending this ObjectTrigger<T> generic class and implement the OnTriggered  function:\n\n```\npublic class SimpleHazard : ObjectTrigger<PlayerController>\n{\n  protected override void OnTrigger(PlayerController player)\n  {\n    player.OnHit(transform);\n  }\n}\n```\nThere's also this functionality with the triggers where you can create \"proxies\", so that you can add \"external\" hitboxes that are detected as the class they proxy for. I really want to use this one day for a boss where it just has lots of spots where you can hit!!!\n\n```\npublic class PlayerExtraHitbox: IProxyFor<PlayerController>\n{\n  [SerializeField]\n  private PlayerController player;\n  \n  public PlayerController Owner { get { return owner; } }\n}\n```\n\n## Jam Made Systems\n### Audio\nI always have a hard time using unity's audio system. I just find it super hard to do even simple behaviours with it, and there are a lot of recurring problems, like a sound effect increasing in sound if it's triggered multiple times in the same frame. For all of those reasons, this jam I finally built a little sound system. It's far from perfect, and not very optimized for a big scale game, but it worked pretty well for the jam!\n\nHere's how it\u2019s used:\nFor each individual sound effect in the game, you create a sound effect asset like this. You can configure some stuff in it like what audiomixer group it outputs to, and a minimum play interval so you can stop it from triggering multiple times in a frame\n![unnamed.png](\/\/\/raw\/3aa\/e1\/z\/29c8b.png)\nThen you add it to the audio database\n![db.png](\/\/\/raw\/3aa\/e1\/z\/29c8c.png)\nAnd you can play it in your game either by id or by the asset reference\n\n```\n   AudioManager.Instance.Play(\"transition_end\");\n```\nThen in the game it just creates the needed audiosources\n![audioplayers.png](\/\/\/raw\/3aa\/e1\/z\/29c8d.png)\n\n### Events\n\nWe built a nice event system for this game. It uses strings for event ids. I was a bit skeptical about using a system with strings for the events instead of just adding c# events to the each of the game's modules. In the end, I really liked how the string events allowed you to build stuff just through the inspector. I guess in the end both c# events and string-based events can coexist  serving different functions!\n\n\n```\n   TriggerManager.StartListening(EventName.OnBossSpawn, OnBossSpawn);\n```\n\n\n## Final Thoughts\nSo those are the systems we used for building our game. Again, the whole code is available at the [project\u2019s repo on GitHub](https:\/\/github.com\/AntonioHR\/LD45), so if you think any of these could be helpful, feel free to use them! \n\nFor more on our jam process, here's some other posts by our team, as well as our game\n\n[Level Design](https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless\/bloodless-level-design-process)\n\n[Sound Design](https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless\/bloodless-sound-design-process)\n\n[\u30d0\u30af\u30e9\u30a6 Bloodless](https:\/\/ldjam.com\/events\/ludum-dare\/45\/bloodless)\n","title":"\u30d0\u30af\u30e9\u30a6Bloodless | Reusable Code ","wayback_source":[]}