Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by unity_UaKEscun_Mpx-g · Apr 30, 2021 at 09:18 AM · scriptableobjectmonobehaviourdependenciescircular

Circular Dependency Issue

Hi,

I defined a MonoBehaviour, a ScriptableObject and a basic class to describe how my characters function:


Player.cs: ScriptableObject that holds information about a Character ( Damage, Name, Price, Attack Speed etc.), the data here shouldn't be altered in any way (Like increasing the damage or changing the name).


PlayerData.cs: Class that represents changeable & savable information about a Character ( Experience, Tier, isPurchased)


PlayerController.cs : MonoBehaviour that represents how that Character behaves ( Shooting/Fighting/Moving)


The issue I'm facing is that I've created a Circular Dependency between those 3 classes: Player contains a reference to PlayerController to know which Prefab of a Player it holds. PlayerData contains a reference to Player to know which character is being described. PlayerController contains a reference to PlayerData to know how much damage is dealt and what attack speed should be used, etc.

Is this a "good" Circular Dependency? I'd like to hear some ideas on how to remove this dependency if possible. Thanks!

Edit: Player.cs has no functions, it is only used to store data for every character.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Hellium · Apr 30, 2021 at 10:34 AM 0
Share

Why does Player need to have a reference to a PlayerController prefab? Your spawner object should have a direct reference to the prefab.

Why do PlayerData needs to know which character is being described?

Without code, it's hard to help.

avatar image oscarAbraham · May 03, 2021 at 06:10 AM 1
Share

Hi, it does seem like Player may not need PlayerController; a reference to a prefab is just a reference to a GameObject. If Player uses Controller to validate the prefab, maybe you could move that validation elsewhere?

Also, this doesn't solve the problem, but it may make things clearer: it seems that PlayerData's Player is never changed and its only used to pass its data to the Controller. That tells me it could be cleaner to pass the player to the PlayerController directly. I prefer to avoid using classes as bridges for other classes when I can.

Now, some subjective ideas about things that can be refactored:

  • Maybe Player should be called PlayerArchetype. It seems like a more accurate description, which could help you think about it differently.

  • Instead of using a prefab, Player could be an abstract class with an abstract method to create new GOs, with each concrete class would holding the data it needs to implement it. It can be nice to have all that defines a particular player type on the same place. I personally prefer to be able to define this kind of stuff with prefabs, though, and I wouldn't go that way if your designers don't code.

  • If Player needs a prefab, it might be overkill to have a separate ScriptableObject. It could be just another component in the prefab. Maybe it could even be integrated to the PlayerController if it makes sense. If one prefab is currently used in more than one Player for some reason, maybe you could use prefab variants instead.

  • This re$$anonymous$$ds me of a Prototype pattern. If it doesn't impact performance, maybe you can combine PlayerData and Player; you could clone a Player inside your Controllers with Instantiate. You can also store a reference to the prototype asset in case you need it; although, usually that can be replaced with a simple id field that gets copied to the instances.

Something very opinionated:
Usually, Circular Dependencies are treated as problem when talking about modules or assemblies; but circular dependencies as classes don't get such a bad rap in my experience. That's not to say that not to say that Circular Class Dependencies don't have problems; here are some:

  • It makes it harder to do stuff like Dependency Injection, mocking in tests, or automatic filling of fields in deserialization.

  • It makes it easier for circular references to exist and harder to track them.

  • It tends to make code more coupled.

    All circular class dependencies have these problems, but it doesn't mean they're wrong. Conditionals make code harder to follow, but we just avoid overusing them. Sometimes it's the most practical way: interfaces don't play well with Unity's Serialization, events can be cumbersome. Example: It's common to have Circular dependencies AND references in hierarchical data; parents store children, and children reference parents to ensure there's only one.

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

122 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Adding inherited class to list 1 Answer

Best practice for many similar scripts in a game? 0 Answers

AudioClip in ScriptableObject 1 Answer

How to reference MonoBehaviour in ScriptableObject? 2 Answers

new Monobehaviour as variable returns warning... 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges