Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to collect resources #38

Merged
merged 63 commits into from
Mar 30, 2023
Merged

Conversation

nucleartide
Copy link
Owner

@nucleartide nucleartide commented Mar 23, 2023

The Job Story

Player: When I press E, I want to mine a resource, so that I can collect the resource once done mining.

Notion

Provide a link to the Notion block corresponding to this job story.

(Sorry folks, these blocks are internal to my Notion workspace!)

https://www.notion.so/nucleartide/Mechanics-get-started-on-implementation-Be-able-to-collect-raw-resources-229d064b587147a193b925a8095af759?pvs=4

Deliberate Practice

Write down one skill that you'd like to improve in this pull request.

Examples: Knowledge of a package. A sub-skill, such as creating particle effects. Putting in more hours (effort). Working more efficiently. Time estimation.

I want to get more done in 1 day. Ideally, 1 user story a day!

Development Checklist

Run through the following steps to complete your work.

  • Product requirements and game design. Flesh these out in the corresponding Notion block. Make sure to consider:
    • Model. What is the user story? (See above.)
    • Action. How does the player perform actions? What inputs are needed?
    • Rules. The underlying mechanics.
    • Feedback. The sensory feedback presented to the player.
  • First draft. Implement a working first pass at the problem. Try to think in modules: modify prefabs instead of the entire scene.
  • Final draft. Once done, perform a general review of Files changed and revise anything that needs to be cleaned up.

Quality Assurance Checklist

Ensure that your work adheres to the following principles.

  • Modular. Are you touching the scene file? If so, can you limit your changes to prefab files instead?
  • Editable. Has any configuration been moved into ScriptableObjects, so that modified values persist even after exiting Play mode?
  • Debuggable. Do you have debug views for the prefabs/systems that you are creating?
  • Learnable. Consider how the player will learn what you implement in this pull request. Are the affordances appropriately communicated with signifiers?

Screen Recording

Record a quick 5 to 10 second clip of your feature in action.

animations.mov

Changelog

Provide a bulleted list of changes that were made in this pull request.

  • Create a StateMachine framework
  • Implement Player state machine using StateMachine framework
  • Add new “collecting” animations for the player, where animations are tied to Player states
  • Some random additions:
    • Create a ThirdPartyAssets framework for referencing third party assets
      • This will be useful when I need to review licenses more closely for distribution
    • Add Incompetech “Manor” soundtrack (but don't hook it up yet)
  • Some project structure updates:
    • Move reusable code into Plugins/ folders
    • Convert Managers from ScriptableObjects to MonoBehaviours
      • Managers require references to Scene objects, so it was hard to justify keeping them as ScriptableObjects, which can only reference Assets
    • Convert more of the Game scene into prefabs
      • Ideally, this facilitates more modular development; you’d only modify prefab files instead of the entire scene file
    • Update pull request templates with new pipelines/workflows

How it works

Explain what you did, how you did it, and why you did it. Discuss any lessons that might be useful to others.

(Note to self: it's easiest to do a stream-of-consciousness write-up of what you did. Remember to write for the Game Codebase Tour audience!)

Updating the Mecanim state machine

If you ignore the numerous detours and tangents 😅, this pull request primarily implements the ability to collect resources.

You can press E to collect any of the resources in the world.

Currently, there are 8 collectable resources:

  • Coal
  • Copper ore
  • Iron ore
  • Wood
  • Stone
  • Sugar cane
  • Water
  • Wheat

Which can be categorized into 3 animations:

  • Mine
    • Coal
    • Copper ore
    • Iron ore
    • Stone
  • Chop
    • Wood
    • Sugar cane
    • Wheat
  • Scoop
    • Water

Implementing the 3 animations required updating the Mecanim state machine for the player.

To keep the implementation maintainable, I used the “hub and spoke” pattern as described by William Armstrong in his Unite presentation.

The idea is to have a single “PlayerState” animation parameter, and to use that integer as an enum for switching between the various animation states:

Screenshot 2023-03-30 at 11 53 13 AM

This makes it nice to add more animation states in the future. You just add a new state, add a transition from the empty state to the new state, and add a transition back to the empty state.

The transition conditions are simply “PlayerState equals <enum integer>”, or “PlayerState does not equal <enum integer>”.

Using the state machine pattern

Because the player had all these different animation states, it made sense to extend these visual states to the underlying logical states as well.

Thus, I implemented a simple state machine framework, where a StateMachineBehaviour MonoBehaviour would selectively enable/disable StateBehaviours on the same GameObject to maintain a single active state.

(So there'd only ever be one StateBehaviour active at any time.)

Also note that you can inspect the Current State. It’s the custom label at the top of the “Player State Machine” inspector:

Screenshot 2023-03-30 at 11 55 40 AM

The PlayerAnimator would then use the currently active state to set the PlayerState animation parameter:

Screenshot 2023-03-30 at 11 55 47 AM

I map between Resources, StateBehaviours, and PlayerState enums with lists of serializable Mapping classes, which I use for lookup:

[System.Serializable]
public class ResourceToPlayerState
{
[NotNull]
public ResourceConfiguration Resource;
[NotNull]
public PlayerCollectingState PlayerState;
}
[SerializeField]
private List<ResourceToPlayerState> resourcesToPlayerStates = new List<ResourceToPlayerState>();
private PlayerCollectingState GetPlayerState(ResourceConfiguration resource)
{
foreach (var mapping in resourcesToPlayerStates)
if (mapping.Resource == resource)
return mapping.PlayerState;
throw new System.Exception($"Resource {resource.name} does not have a corresponding PlayerCollectingState. Please double-check the resourcesToPlayerStates mapping, then try again.");
}

Lookup is not as efficient as a Dictionary, but it gets the job done! Besides, the list is only a few elements long.

Pipelines

While doing all this, I realized that the player may have even more animations in the future. Perhaps for building structures, or performing any of a variety of crafting animations.

So I added a few more checklists to the .github/PULL_REQUEST_TEMPLATE/ directory. Reducing the creative process to a few worksheets makes the work far more approachable.

You don’t need to think; you just follow instructions!

(And yes, the irony of making a factory building game while optimizing my own game building process is not lost on me.)

I’m excited to juice up this mechanic in following pull requests. Sound is first on my list of priorities.

Final Checklist

Perform some final tasks for sign-off.

  • Update readme with new pull request

@nucleartide nucleartide marked this pull request as ready for review March 30, 2023 16:12
@nucleartide nucleartide merged commit 657e386 into master Mar 30, 2023
@nucleartide nucleartide deleted the jason/collect-resources branch March 30, 2023 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant