#archived-code-advanced
1 messages Ā· Page 28 of 1
however i am sort of confused what you are trying to do... based on the example how is updating a health bar related to setting the adaptive shake
you can make a fluid API (what this is called) for anything
doesn't mean you should
Yeah i did that but it is run before chained functions which already passed values to dotween
Well health bar has its settings for example how long it should last, i wanted to add override function that enables it to last for different duration, that call only
Then you'd make a builder class or struct that wraps around it
You can also always save Tween as variable and modify it
but it cant be modified after running also how would struct delay animation start in Update function, after chained functions have been ran
i tried looking dotween code but couldnt find much how they do it
i would says making Update function Coroutine and then waiting 1 frame before calling animation
just to be clear Update function is UpdateHealthBar, not unity Update
Can someone help with the code architecture, please? I did a state machine for my actions (attack, move and idle). I have a state manager (this is my context, mono), character base state (abstract class) and classes that inherit from the abstract (move, attack and idle).
Then, I have PlayerInput controller, which has different actions (mouse click, key pressed, etc), and I want this class to switch state. However, I need to pass in the info (for instance, vector3) from PlayerInput to , for example, moving state. What is the best way to implement it? Is it a good architecture?
Another question I have is my moving state have moving logic and animation logic. How should I separate it to follow single responsibility principle? (animation and logic in different classes?)
Why not creating events for this purpose, invoke them in your Input Class and simply add the required callbacks in your actual base class? That way you can also simply add further events for animations and so on
https://learn.microsoft.com/en-us/dotnet/standard/events/
that's a good idea. No idea how I missed it. Thanks
So, event is invoke in the playerInput and it switches state to let's say move
or abandon state machine all together?
you can still use the state machine, and subscribe to the events send by your player input, but I would try to abstract the input itself as it's pretty nasty to get e.g. cross controller support even with the new input system if you're putting your inputs in the programming
i used new input system for that
thanks
ia.default.action.performed += callback => yourCurrentState.WhatDo(callback.ReadValue<Vector3>);
or if you're using the component,
OnWhatever( CallbackContext callback)
{ yourCurrentState.WhatDo(callback.ReadValue<Vector3>); }
or something like that, i'm not using the component so i'm not 100% on that
what does UpdateHealthBar do?
is there a way to edit instances of a monobehaviour derived script from its inspector reference inside of another script?
basically postpone running of update until all chained functions are complete
i don't get it, why not just write it that way
write the fluent api so that the last call is update
it doesn't make sense
Basically set some sprite colors, transform positions and run dotween with some settings.
I wanted to achieve dotween style of fluent, basically say what you want and then chain the settings. Doing updatehealthbar as last just bit clunkier
Was looking at dotween source code but had enough after about 2 hours š„¹
okay this is how it looks
class HealthBar : MonoBehaviour {
Sequence sequence;
int frame;
private void SetTween() {
if (frame != Time.frameCount) {
frame = Time.frameCount;
sequence?.Kill();
sequence = DOTween.Sequence();
}
}
public HealthBar SetShake(...) {
SetTween();
sequence.Insert(0, transform.DOShake(...));
return this;
}
public HealthBar UpdateHealthBar(...) {
...
}
void LateUpdate() {
// or whatever the method is
if ((sequence?.IsPlaying() ?? true) == false)) {
sequence.Play();
}
}
}
@flint wraith does that make sense?
there's something here i don't understand because it seems pretty straightforward to me
UpdateHealthBar().SetShake() would work?
this is basically dotween style
transform.DoScale(2f, 2f);
or you can do
transform.DoScale(2f, 2f).SetEase(Ease.OutQuart);
in my current model i must do
UpdateHealthBar()
which is ok but if i want to add settings i must do
SetShake(1f).UpdateHealthBar();
meaning UpdateHealthBar MUST be at end
basically looking if there is a way to postpone UpdateHealthBar until chains are complete
if you have autoplaying sequences, then yes
i'm pretty sure you can modify the sequence after you have called play anyway
they're separate concerns
i mean look at the code
it shoudl be apparent that it's separate
hmmm doesnt seem that i change tween settings as vibrato, duration, strength and so on after i create it.
with late update it makes sense, i thought about that also but seems bit clumsier
If I have a set of derivative classes I want a user to be able to choose between from within another class, how do I enable that ability? I want there to be able to be multiple instances of the same derivative type, but for each derivative type. My original idea was to have a private array of the base class, and a public array of each derivative type whose elements I feed into the base class array so I can iterate through them all from the one base array. Is there a better way to do this?
Does anyone here know how to properly reference an asset and save changes to it through the editor? #āļøāeditor-extensions message
I have an IMeshModifier that offsets the verts of the Graphic but of course GraphicRaycaster is not aware. I temporarily move the Graphic's Rect where its verts get offset to just before GraphicRaycaster runs and back after, works well, but OnRectTransformsDimensionsChanged gets called and everything gets set dirty and performance is terrible
public class BuildingDismantler : MonoBehaviour {
[SerializeField] private Sprite _hummerSprite;
private Entity Building => RaycastBuilding();
private EntityCursor BuildingCursor => EntityCursor.instance;
private bool _isDismantling;
private void Update() {
if (Input.GetKeyDown(KeyCode.Mouse0)) {
TryDestroyBuilding();
}
}
public void ToggleDismantleMode() {
if (!_isDismantling) {
_isDismantling = true;
BuildingCursor.SetCursor(_hummerSprite);
StartCoroutine(CheckBuildingContinuously());
} else {
_isDismantling = false;
StopCoroutine(CheckBuildingContinuously());
EntityCursor.instance.HideCursor();
}
}
private void CheckBuilding() => BuildingCursor.SetColor(Building == null ? 0 : 1);
private IEnumerator CheckBuildingContinuously() {
while (true) {
CheckBuilding();
}
}
private void TryDestroyBuilding() {
if (Building == null || !_isDismantling) return;
Building.DestroyEntity();
ToggleDismantleMode();
}
private Entity RaycastBuilding() {
var hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (hit.collider.TryGetComponent<Entity>(out var building)) {
return building;
}
Debug.LogWarning("No entity found.");
return null;
}
}```
Can this code be considered as a good one? I tried to follow all the principles.
@runic girder great, now switch over to NIS (new input system)
also Try without returning a bool makes me uneasy, usually you'd return it to make some kind of error sound if it fails
NIS?
Gotta read about it
it's easier to switch early in the project, and it's definitely worth it
This project is about to be released xd
well, if it's targeting only MKB (mouse + keyboard) then it's fine for now
what's MKB?
@runic girder your ToggleDismantleMode has a check that's unreachable
trydestroy returns if !_isDismantling, so in toggle you don't ever get the first part
I am actually going to use ToggleDismantleMode on button in editor, so it's fine, is it?
yeah, it's fine. i'm also not sure if coroutine stops if you do it like that instead of caching
i just tie everything to a bool
Yeah, I've tested it, works fine
e.g. in coroutine { while(_isDismantling){ ... } cleanup }
I actually tried to avoid it here. Wanted to use this coroutine only in specific moment
Otherwise this coroutine would run endlessly while checking If(_isDemantling)
yeah, but then it's being stopped when program toggles Dismantle Mode off
Ohh, I actually just get it
i also don't see what's in CheckBuildingContinuously, does it return wait?
It simply sets the building cursor's color
0 = red, 1 = green
yeah, and it converts bool to int
wellllll xddd
you didn't even test the code, did you? ahaha
I actually didn't ahaha
it'll definitely crash ahaha
easy to fix tho
in any case, if you don't need checkbuilding separately, i'd just move it right there, it's less confusing that way
private IEnumerator CheckBuildingContinuously()
{ _isDismantling = true;
while (_isDismantling) { BuildingCursor.SetColor(Building == null ? 0 : 1);
yield return CACHEDwait; }
}
public void SetColor(int index) {
if(_cursor.color != _colors[index])
_cursor.color = _colors[index];
}
Fixed
Yeah I already did it
but wait
what's yield return CACHEDwait?
if it's not null, you can cache it so that it doesn't generate garbage
for a building highlight you probably don't want it to be running at 120 fps, or even 50
private IEnumerator CheckBuilding() {
while (_isDismantling) {
BuildingCursor.SetColor(Building == null ? 0 : 1);
yield return new WaitForSeconds(0.1f);
}
}
So you mean this, don't you?
cache it
static WaitForSeconds 100ms = new WaitForSeconds(0.1f);
then you can just return class.100ms; from anywhere
and it always sits in memory instead of dozens of copies that need to be cleaned up with GC (unless i'm totally misunderstanding how it works)
static readonly WaitForSeconds CachedWait = new(0.1f);
private IEnumerator CheckBuilding() {
while (_isDismantling) {
BuildingCursor.SetColor(Building == null ? 0 : 1);
yield return CachedWait;
}
}
this way?
yep
btw, why should I make it static, Rider says I should do it, but why?
1: instances won't generate a new one
2: you can access it from other classes without a reference, instead of making a new one
yw, good luck with release
thx!
Does anyone know the math behind Transform.TransformPoint and Transform.TransformVector methods? I store positions in a struct, so I need something to perform the local to world transformation without the original transform.
I thought about it yesterday. So, the event subscribes to a function inside an instance of a state. Then, i have a logic for movement inside of my state and have another class with animation that is called by the event
Right?
do we have any way to "intercept" any asset loading of some kind? e.g. when a model is loaded, get that model and add it to a massive buffer alongside many others, and prevent the "original" model load from actually being loaded into memory? my main goal here is to use said buffer for MultiDrawIndirect commands
Look into Matrix4x4
Hi everybody, is it possible to use physics to grab parts of a mesh ? I have a character with a ponytail which has no bones inside. I was wondering if it was possible to create a script (or if an asset on the store already does that, I don't mind paying) which would allow me to move the ponytail with the mouse at runtime. Like grabbing the end of ponytail with the mouse, drag it around and it would follow the cursor. And if we grab it in the middle of the ponytail, the correct part would be dragged while the end of the ponytail would be affected by gravity and velocity.
The assets I found online only use either bone or the whole mesh
Put some bone and skin it
Unfortunately, I'm not good enough to do that :x
there was a really nice asset on the store for that kind of thing
Itās much harder if you try to do without bones
Hm, is it possible to add bones in unity ?
Oh? Would you have its name?
Another option is to use blend shapes, but for this you also need a 3D editing software. And bones will yield better results.
Though blend shapes might be easier to generate by code, than bones/bindposes
I see. However blendshapes would feel less natural than bones or physics I guess.
OK thanks a lot, I'll check it!
besides that it's better to just make a bone though
just import to blender and do it from there
royalskies has a really nice and short tutorial on that
https://youtu.be/X590IZeyT1s
Yes but in my case, it's quite tricky. I'm using Daz3D assets, hair and cloth and editing them is really tricky, plus I'll have a lot of them so editing all of them would take a lot of time.
yes, I've tested it and it does give a goof result but there is not grabbing feature from what I tested.
Ahh, I missed the "move with mouse" part
The ponytail does get proper physics and interact with chosen colliders.
either way yeah it's possible, but is it really a game-changing feature?
like, would you spend a month working on that?
Well, yes it would be quite needed since I'm aiming at an
"adult" game in the end where I'd like cloth to be removable with the mouse haha and hair to be pullable š
But when you say it's possible, I still don't see how it would work. All assets I found and even the one you linked are based on bones. So unless I modify hundreds of purchased asset to add bones, I still can't see a solutiion.
Which was why I was focusing on how to modify mesh partially, moving vertices individually but the math behind would be complex.
boing description says you just add component and it should work
no clue about it myself though
Primarily for my students at FutureGames - I will only read chat/superchats during breaks!
Assignments here!! ā± https://acegikmo.notion.site/Lectures-Assignments-a4419295f33f46c3af113eb74b407607
Find out more about the school at https://futuregames.se/
ā FAQ ā± https://acegikmo.notion.site/FAQ-8b62a1634746473db702565d890dd3dd
š Support me on P...
i'd just add bones since that's the most reasonable thing to do
From what I read "- The core logic for boing behaviors and reactors are simply modifying object transforms, so it should be compatible with all platforms Unity supports."
OK got it. I'll keep that in mind then when I have something more stable, it's not a critical feature as you said but would be a nice addition.
@muted root but on the other hand, boing is 50% off, although you can see hair breaking there
Thanks! This is an amazing lecture.
@shadow vigil yeah, have fun binging on the rest of the videos āØ
I have an issue with the duplication of a class and it's members. I've been looking at Deep Copy options and I'm having trouble coming up with a good one that meets my requirements. I'm duplicating a class that contains members of another namespace down-casted to it's in-namespace base class and I want it to be oblivious to what the derived classes are.
- This means that probably Copy Constructor won't work, as that class' duplication method can't access the other classes in other namespaces. This is a limitation of assembly definitions, as it doesn't support cyclic dependencies.
- I'm assuming that
JSON Serializationcreates a deep copy and it also is being a problem since one of the members of the duplicated class can be anUnityEngine.Objectand is notSerializable. I do need to save that reference and It's currently declared as[SerializeReference] private Object owner(could addMonoBehavioursupport in the future). On this option I tried to find the asset by name (all names are always unique), but doesn't really work as it doesn't let it run during serialization ({ get; set; })
at which point do I need to use LinkedPool? I find that ObjectPool is sufficient but is there any specific use case where I need to use it?
https://docs.unity3d.com/ScriptReference/Pool.LinkedPool_1.html
ObjectPool should more efficient, if you have more or less stable pool size and LinkedPool perform better, if amount of pooled object fluctuates.
but why? what are you trying to do?
you're overthinking this. you will never need this API. you will never need to animate the health bar from the outside, the health bar should animate itself
Curve UI around a cylinder, the curving works, the GraphicRaycasting doesn't
can you share a screenshot?
Beautiful!
quick question so i have coded a state machine to control all of my movement walking running jumping also included flying and all the transition substates . now i want to add 3rd person shooter controls would it be better to expand this state machine or create a second set of scripts
Does anyone know how to blend two meshes into one. Like I wanna do an ocean with some very low vertex displacement with no subdivided ones. And then I have the waves around the player that should look high quality and very detailed and so on that plane is massively subdivided. How can I now blend the ocean with the player waves?
To get a smoother transition between high waves around the player and the low ocean waves
May you explain? xD
Like how can I do then tesselation?
And I need it as code.
tesselation its a large topic might take a bit but its ideal for this case
Yeah, I know.
though keep in mind you really do not need to combine or blend meshes
you can have 2 meshes look seamless
But I only see shaders for tesselation. But I need to script it.
just as long as on the boundary the vertex positions and normals are the same
.
Yeah, I would need to script it.
yeah what you are asking with the waves, doing it in shader is the ideal place to do it
But I need to make buoyancy. A boat should drive on it and a player should swim on it
And also like explosions and some other stuff....
since simulating water is a lot of per vertex work, so vertex shader is ideal, or compute shader for just doing the work fast and getting some sort of output
But I need high waves
it is a big topic, but you might be able search for ocean simulations and other stuff to get a grounding in it
yeah assuming you are wanting somehting like sea of theifs
And came to the conclusion that vertex displacement in scripts is ideal....
Similar
yeah that is heavily vertex and compute shader driven
Yeah
But I need to dynamically recalculate the water height at x and z
Wait...
I could just do my general vertex displacement and then tesselation in a shader
Because I would get raw, low quality waves for physics but goodlooking ones as an actual output
yeah could do the mix, generally physics wise it would be smaller
still might use a compute shader for that, since the resulting data from it you can use in code, but will run much much faster
though really depends on the resolution, if its a small enough amount of points it runs fine in C# can just start off with that
Yeah
But generally, how would I simulate those lots and lots of random waves...
I got Gerstner waves for now
would have suggested gerstner or driving it with a texture
can get randomness changing some of its input paramaters at runtime or having multiple generations of them
Perlin Noise?
could work, but even multiple generations of waves you scale down in height and multiply with previous ones can add a lot of variation
and let you have detail and multiple scales
Yeah
So, what I would do know, is vertex displacement for a radius of 11f, then tesselation from 10f to +11f.
your asking the right questions, its just going to be fiddly to get the look you want
The topic is super interesting, in my view.
Like simulating nature... There's always some randomness.
yeah, if you do try and multiply in noise, i would use perlin since you need things that do not jump too quikcly betwene values
Yeah, then simply Mathf Perlin Noise?
depends on your code, and where the work is being done, but yeah should work, but you will have to play with what you pass for the x any y so the scale of the noise is correct for your usecase
X and Y, not Z?
so those will have to be based on the location you are wanting to get the value for, but you may need to multiply them larger or smaller to loosen up the noise and get more macro scale detials or tighten it up
Yeah, I am gonna have a lot of public floats for tweaking xD
but yeah since you mentioned needed different levels of detial you can fake it without tesselation
would just make a grid of meshes, where the ones closest to the player have a higher vertex density
the important part is just making sure the positions and normals of the edges match up with there neighbors
Yeah
But like that part of changing the vertex density is my Problem....
But the best way would be tesselation?
How would I do it then with a shader (having a circular shape)...?
I have a question. I do very little multi-threading, and I was wondering how would be a good way to go about using multi-threading to create a mesh with a more advanced structure. In this case I mean a BMesh (specifically this lib https://github.com/eliemichel/BMeshUnity).
Like it requires adding items to a list and referencing things and stuff which multi-threading doesn't like.
Just kind of looking for a 'high level' overview of how one would approach it.
adding things to lists and referencing things are not problems for multithreading in Unity.
Accessing objects that are managed by the engine from a background thread are.
So the specifically problematic part about using BMesh in a multithreaded environment would be that this method in particular needs to run on the main thread:
https://github.com/eliemichel/BMeshUnity/blob/3360cb6e2397dc0efb7137d6551ac60dd7dc6879/Library/BMeshUnity.cs#L48
Yeah I know... I am kind of stretching the limits here of what is considered Unity and not just a normal C# question....
Doesn't adding things to lists in multiple threads cause problems in C# as two threads may try to put something in the same spot... or something...
(It really has been too long since I have done any multi-threading...)
Yes adding things to the same list from multiple threads can be problematic
but that wasn't implied in the original question I don't think š¤
Was it not? I thought it was, sorry. It has a bmesh.AddVertex(..) method and a number of others that are used to construct the mesh.
Those of course, add the specified vertex/edge/face to a list on the mesh
Yeah you'd have to stray away from those or use proper synchronization constructs around them.
The other approach is to preallocate the vertex lists and only Set vertices etc. in existing locations which you assign to different threads
I see, that is kind of a large reason to use them.
All vertices are connected (reference) edges, which reference faces so generally you will need to cross reference things.
I guess generation can't really be multi-threaded too well.
Though modification can be.
Any vue 3 user here?
Would this work, I don't think so cause It says that Surface Shaders aren't supported for URP? https://docs.unity3d.com/Manual/SL-SurfaceShaderTessellation.html
am i crazy for not using a gamemanager?
idk just never liked the idea of it
could just be that its not useful in the game im making but it just seems to be a catalyst for bad code imo
It depends on what you're using instead of a gamemanager
It is a really useful design pattern, but yes people tend to use it a bit too often.
For example in my game I have a tile/grid system that basically everything has to access, so it makes sense to use a singleton
What sort of game are you making?
GameManager holds the parts of your game that are tightly coupled with each other. another example is Player, because a lot of people make games where input is tightly coupled with animation
they are not supported yet
i control that from the player itself
makes more sense to me than a third party manager to do it
yeah, so if it makes sense to you why you have a Player class
that listens to input and then also drives animations
and does a bunch of other stuff
that is "coupled"
nah its all separated components
i just have a reference to my animator in PlayerShooting and set stuff from ther
the kind of game you're making decides whether or not something like animations are tightly coupled to input, not your class structure
does that make sense?
yeah
yeah that's all i'm really saying
if it's Spelunky, there is very tightly coupled player input, behavior and animation
most platformers look that way
compared to an RTS, where it is usually totally decoupled
you have to do the coupling, if it's right for your game, somewhere
some people like to suffer, and couple things using Dependency Injection
oh hell no lol
some people put the coupling in... a class. which in my opinion, is a good choice
of all the bad choices, it's a good one
a lot of people are making spelunky, then roll a state machine class, and it's hard
they have a state machine engine, and exactly one state machine (their player character in a platformer or FPS)
they have dependency injection, and exactly 1 implementation of every interface (service, or whatever)
Not sure if itās actually that common things are tightly coupled in something like spelunky for example. I would guess itās more like coupling through abstraction and for example all characters are ābuilt the same with different kind of componentsā
you can only make that kind of retro/legacy/traditional 2d platformer input behavior by tightly coupling input and animation
how you choose to express that tight coupling is up to you
you can use Zenject to do that, and call it decoupled, and of course, it's actually coupled
you can also be in denial that there is some decoupled form of input behavior for that game, and if you try to make that, it won't "feel right"
there just isn't. all that retro platformer stick input movement behavior feels the way it does by harnessing the power of tight coupling
that's why i bring up RTSes, which have a huge variety of movement behaviors for units, and input is almost always as basic as clicking on a map
so of course that is decoupled
Iād say tight controls are no way related to tight coupling
there aren't any RTSes with tightly coupled movement and input
"tight" for a platformer... nobody would use the word tight to describe movement in an RTS
it's a very very retro thing
Spelunky like characters donāt care if their animation is driven by input or ai or whatever as long as the change is instant and there is no inherent delay in something like interfaces
you can use Zenject to do that, and call it decoupled, and of course, it's actually tightly* coupled
you can certainly engineer those things however you want
kind of the core of @surreal vessel 's question
and i get it, you look at a GameManager and it has "all these lines of code" in it
many alternatives, for certain genres of games, are worse
yeah and i suppose also depends on the scale of your game
my current project is prety ambitious so a gamemanager for one off things wont do
another perspective is, you can find innovations when you go really hard one way or the other. like if you really want to make an innovative platformer, consider what player input would look like if it was highly decoupled
i'm not saying there is an audience for platformers with innovative controls - there problem is not - but you could do something cool there maybe
well maybe gimme a 1 sentence logline, i know you said it was a roguelite (or roguelike)
openworld, dungeon crawler, bullet hell, roguelike
what i have seen is the levels are usually highly decoupled
because most of the innovation is in the encounters / enemies / terrain / items / etc.
and you build that up iteratively, and the interesting stuff sometimes happens when it's emergent behavior. like your player has the ability to turn land to water, and a water creature can now change its habitat, and this is emergent, it only happens serendipitously because the three systems - player inputs / "spells", terrains, and creatures - are decoupled
it is not valuable to decouple the actually like, turning your joystick into movement
and animating the character in response the joystick
it just has to work a certain traditional way, that people expect
and there's pretty much no innovation there
that said, you can subvert expectations*
maybe it's a game where you take control of other creatures
I think you are just messing up terminology here and talking about something else than āclasses being dependant of specific classesā vs āclasses being dependant of abstractionā
maybe it's a game where you can control things with your joystick, and there's something fun there, like the flow of water or the mood of a creature
you can also consider something tightly coupled for your world - maybe the world is generate from a set of storypoints you carefully design, maybe it's something like monument valley levels with npcs with specific dialogue
it seems like we all know what i mean by tightly coupled. if you wanted to diagnose if something was "tightly coupled," for example, it's a method that is called in exactly one place only. paraphrased from real world:
void Update() {
...
HandleInput();
HandleAnimation();
HandleSound();
}
or it's a code fragment that is called repeatedly in many places. that is something tightly coupled that is usually disguised as decoupled. some stuff i've seen in real codebases
enemy.GiveItem(item);
GameEvents.instance.OnItemGiven(enemy, item);
or
target.Health -= damage;
if (target.Health < 0) {
target.DropAllInventory();
target.Destroy();
GameEvents.instance.OnTargetDies(target);
}
you can create a PlayerInput class and call it from Player... but the methods would only be called from one place
or you can have all that code in the same class
it's not about how many classes. coupling is the hard meaning of, would this thing only make sense together with this other thing?
most platformer input doesn't make sense by itself. it doesn't do anything by itself. for a long time, it was all of Input.GetAxis
Anyway, itās not matter of coupling or using managers or whatnot if things are possible to do (like tight controls), but how simple or hard things get when you start expanding the system. No reason to do decoupling for sake of it, but itās usually in the end simpler to design for example animation system which can be driven by anything instead of having one system for player, another for second player with a bit different skills and again different kind of animation systems for different kind of aiās and so on
yeah but you'd never need to expand something like a platformer's movement behavior. like either it is complete to spec, or it is not finished
there are basically no platformers that operate as services games, and none of those introduce "a new way to move around based on your joystick input" if that makes sense
for a 2d platformer, the design space of your level geometry is š± tightly coupled to your player input, because the movement of the player is
i'm not saying you have a piece of code that calls Input.GetAxis to determine how you, in your brain, lay out platforms
but that you have to account for how the player moves.
but how simple or hard things get when you start expanding the system
so my point is, you will just never do that. you have to do something like build your player input for a 2d platformer in 1 shot, and it has to be fully specified - maybe not done in an engineering sense, but a fixed design quantity - before you start building your level
and in my experience, this is why people building 2d platformers don't really develop skills ot build other games...
like shipping a 2d platformer is anti-experience
isn't that nuts?
i don't know about animation either. the way megaman is animated, because it is so tightly coupled ti player input - it's like a special part of those games, those super traditional platformer inputs, how you read the animations and the specific pixels and whatever to know how the player behaves - none of that translates to an NPC
it isn't relevant
you don't control the npcs. so of course they can use a state machine for animation, which is much simpler
and i understand the megaman player has something that resembles a state machine, but the actual code for those games looks like a severe case of Updateloopese
where the update loop has very fine tuned interactions between which frame of which animation megaman is showing in response to which timers and which inputs
you're not wrong, it's just that these sorts of games, they don't ship with flexible animation systems
they could ship with them, and it would be wasted effort
and probably get in the way of achieving the thing those audiences want, which is almost uniformly megaman controls
can you tell i really hate the guts of 2d platformers
š Yeah, I get what you are saying and not denying this isnāt the case (especially for anything actually 8bit - you totally canāt look at that stuff through the lenses of modern game development), but funnily the roguelite part was one which threw me towards the āgo with the abstractionsā route in this discussion. Itās quite common you actually want to expand lots of systems in games like that and have systems which allows you to develop crazy ideas easily
that's true
So that one day when you want to give all the enemies skill to block like players block, or climb the ladders or give player ability to control enemies or something you donāt end up with spaghetti
it's so hard to innovate in the levels & enemies without it being nicely abstracted
then again, every time i try to show people, "you're trying to make a CCG in addition to megaman, when you sign up to do an open world roguelike"
that gives the poor guy a heart attack
you donāt end up with spaghetti
in my experience the best approaches are, can you make strategy card game text that describes the parts of your world you'd like to emergently combine together, and limit the design space of that text to something you can achieve in engineering
then you can avoid spaghetti - spaghetti is like, all the interesting card text you want to do, but you have to touch a bajillion things to achieve it
signing up to author XMage on top of your other game is a crazy move
XMage is nicely abstracted and has thousands of bugs
they are tractable to fix but nonetheless, if you wanted the Whole Design Space of Magic the Gathering, you're gonna ouch
we really gotta see the source of Rimworld
to know how far basic approaches to this stuff can go
Wellll, itās not like physical card games donāt have bugs so to speak. Except in their case bugs are solved by house rules or developer blog posts or by additional rules enforced by tournament organizers etc
(Had to check, mtg rulebook is 278 pages long. I must say that is quite a lot for a game which tries to describe everything relevant inside a short card text)
yeah hearthstone has a limited design space, like no change in priority, that poops away a lot of the complexity
paper prototyping a roguelite where input doens't matter as much is a Good Idea
you can definitely do this, as a creator, and make an innovative one
i am biased because i hate megaman controls, but what do i know, look at Shovel Knight
until you suddenly decide to try to add anti-gravity and/or vr
or to combine dash with attack that depends on weapon
there's always a game designer leaking creativity deciding to breaks previous mechanics in some way
Hello, I am syncing my project to a new PC and am getting compiler errors relating to duplicate type definition in .Net and MSCorlib. here is one such error: ```Library\PackageCache\com.unity.services.core@1.0.1\Editor\Core\AsyncOperation\IAsyncOperationAwaiter.cs(35,47): error CS0433: The type 'ICriticalNotifyCompletion' exists in both 'AsyncBridge.Net35, Version=0.2.3333.0, Culture=neutral, PublicKeyToken=b3b1c0202c0d6a87' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Any idea what might be causing this and how to fix? Presumably I can't edit MSCorlib.
It's also working just fine on the original PC the project was made for.
duplicate files, possibly in different folders
So it's definitely something within the Unity project?
wdym unity, it's a C# error
it's trying to rebuild it but found 2 types with same name
Hmm. Updating Visual studio and re-syncing the project from github seems to have fixed it.
Though now the .sln says I need to update Unity for Visual Studio to use any code tools.
Is there some callback function for when an animation transition has ended?
There's https://docs.unity3d.com/ScriptReference/StateMachineBehaviour.html
And there are animation events
I am making a server plugin for the game Rust and I want to display some fancy GUI, I know that rust uses Unity's UI system and I want to send a command to the client to draw something, this is done via RPC. Now the problem is that I dont know what data to send, so I started reverse engineering and now im stuck at some method that is loading some unity asset in which I pressume there is a value which was set in the inspector because in the decompiler the field is not initialized
So the tldr is where is that inspector value stored and can I somehow see it?
I tried almost all unity resource extractors/resource viewers none of them give the thing I want
Any help appreciated!
What can I do instead? i really just want high quality waves (high subdivision) in a radius and outer waves around that aren't subdivided.
And the radius position would be the same as the player's.
I am currently working on a water shader that has animated waves (based on a sin wave) made through the shader itself, but in order to get the motion...
what are your target platforms?
Windows
how do you feel about using hdrp
I don't mind. I can use it too.
I just want to get it working.
Really, it doesn't matter.
well hdrp has tessellation support
it is much closer to the Unreal / high fidelity gaming pipeline
But how can I do it then?
It says that HDR is unsupported.
what is your objective?
what are you trying to make?
https://youtu.be/ycJ434Lh21w?t=583 here is an example of tessellation in hdrp
In this shader tutorial, I show you how to use tessellation and displacement to create incredibly detailed meshes without paying for high polygon counts. I show how to adjust the tessellation so you get triangles right where you need them and remove them where they're not needed.
Here's last week's video on creating the specular highlights for ...
i'm worried you're talking about surface shaders
.
I want that.
Highly subdivided waves in a radius (with a shader), and out of that radius no subdivided waves.
when you say waves, you mean you want to make an ocean?
I did that.
like the purpose is to make a water effect?
Let's say a plane
are you doing this using shader graph?
No, code
so
i think you can use built in render pipeline then, and proceed along
there's a reason surface shaders were eliminated from hdrp
ok
and why they haven't really bothered with reintroducing them in URP
ok
i can't tell if you're interested why
it sounds like you want to write shader code
which is the problem
No, it is not
if your goal is to create attractive looking water
I think you don't understand me.
The water shader is working and looks good.
I just need tesselation for extra smoothness
hdrp has a water surface you can experiment with and extend
its behavior is similar to what you find shipping in many games, and is meant to be a clone of whatever unreal has
But I need high waves and low ones-
I need to dynamically generate those
Low waves around islands and then higher ones based on distance
there might be assets that do this too
But when I use the buit-in, I don't have shader graphs right?
So, my written water lit shader won't work
i don't understand, did you write a coded shader, or did you make a shader graph shader
i think you'll figure it out sorry i can't be of more help
shader graph
Instantiate(pmag, parent: Magparent.transform, position: new Vector3(0.0657f, 1.3951f, 1.0043f), rotation: rotation2);
How to make it instantiate in local certain coordinates (inside magparent)? Now it spawns in world position (изменено)
As I told you yesterday - you can't. You have to give it a world position.
So you could convert your local position to the world position you want. E.g.:
Magparent.transform.TransformPoint(new Vector3(0.0657f, 1.3951f, 1.0043f))
weird to have a hardcoded offset like that though
recommend just adding an empty object as a child of Magparent at the correct location
and use that position directly
e.g. theEmpty.transform.position
Ok, thank you, it is hard to undestand for me
I'm not sure how is this advanced topic, ...for example just rotate offset vector and add your player's position?
Oh, sorry, its advanced for me :D. I have never used the new input system with controller, only for simple Keyboard movement. But ill move my question.
i am codegenerating a class and then trying to create a scriptable object from that class. However i need to wait until the assetdatabase refresh finished until i can actually create the scriptable object. I thought executing this in [DidReloadScripts] is the way to go but ScriptableObject.CreateInstance() does not create an instance because it cannot find the Type yet.
[DidReloadScripts]
public static void CreateScriptableObjectAsset()
{
var folderPath = "Assets/Scripts/UtilityAI/CodeGen/AutoGeneratedRefs/";
if (newCodeGenTypeNames.Count == 0) return;
foreach (var newTypeName in newCodeGenTypeNames)
{
if (!string.IsNullOrEmpty(newTypeName))
{
Debug.Log("Trying to create ScrObj for typeName: " + newTypeName);
var newScrObj = ScriptableObject.CreateInstance(newTypeName);
AssetDatabase.CreateAsset(newScrObj,
folderPath + newTypeName + ".asset");
AssetDatabase.SaveAssets();
}else
{
Debug.Log("newTypeName is null ");
}
}
newCodeGenTypeNames.Clear();
}```
anyone knows how i guarantee that all newly created types can be discovered?
I know the code generally works because when i restart the editor every asset is generated correctly. Its just a timing issue
maybe with an asset postprocessor combined with domain reload detection? https://docs.unity3d.com/ScriptReference/AssetPostprocessor.html
very useful! i didnt know about them. i have the same issue however...
UnityEngine.ScriptableObject:CreateInstance (string)
UtilityAI.ReferenceGeneration/MyAllPostprocessor:OnPostprocessAllAssets (string[],string[],string[],string[],bool) (at Assets/Scripts/UtilityAI/Core/ReferenceGeneration.cs:139)```
this error pops up once but then with PostProcessor it now runs again and creates the object
so its still not waiting just right
its typically used to display those "hey you installed package Foo, wanna look at our website" windows
in my case it wont help. i need to create scriptable object instances that hold a reference to a type that has a implemented a certain interface. those types with the interface are outside of packages and my AI package is trying to reference them
i know sounds stupid but there is an idea here š
i don't pretend to understand
but if its just a question of waiting a bit, why not use an editor coroutine?
but what to wait for? i kinda dont want to use wait 5 sec. (especially since it might be that i create quite a few such classes in some rare cases and it could take longer)
idk, no idea why the type isn't loaded after the domain reload
maybe this detailed illustration of domain reload contains a hint: https://docs.unity3d.com/Manual/ConfigurableEnterPlayModeDetails.html
or poll this property https://docs.unity3d.com/ScriptReference/EditorApplication-isCompiling.html
its crazy. it does not compile but it doesnt find the script
is it referenced by, or part of, the assembly you are operating in?
yes im creating that asset inside my AI assembly where that script is running too. as i said everything is actually created correctly. it just throws this error once before creating it
@compact ingot thanks a bunch for your help! i learned alot
need my bed now š ill find a way tomorrow
so is there any way to profile without a development build yet
i think there is an experimental runtime profiling package right?
the profiler?
deep profiling
hello, has anyone tried synchronizing the selection within UnityEditor.Experimental.GraphView with Selection.objects so you can edit them in the property editor (in my case, nodes are backed by ScriptableObjects)? selecting elements in the GraphView correlated to Selection.objects when Undo.undoRedoPerformed is triggered doesn't seem to help. I see the selection showing up in my undo history, but the GraphView doesn't update with the selection, even though I called AddToSelection with the right elements, which exist in the GraphView.
i am doing it with Selection.SetActiveObjectWithContext(scriptableObjectData, scriptableObjectData);
More advanced C# than advanced Unity, but it's worth asking here.
public struct CategoryTag
{
[JsonProperty("id")] public int id;
[JsonProperty("name")] public string name;
public static bool operator ==(CategoryTag a, CategoryTag b)
{
return a.id == b.id && a.name == b.name;
}
public static bool operator !=(CategoryTag a, CategoryTag b)
{
return (a == b) == false;
}
}
I want to use the equals operator with this struct, but it doesn't recognise them so I had to make my own. This caused a green squiggly line over the struct name and these errors:
'CategoryTag' defines operator == or operator != but does not override Object.Equals(object o)
'CategoryTag' defines operator == or operator != but does not override Object.GetHashCode()
Is this a problem? Can I override the GetHashCode() function and then not need to make the custom operators? What's the best way to implement something like this?
just override equals (as well)
But in that case what would I override it with? I know for GetHashCode() I'll need to make a custom function to generate one from the variables, I presume I'd have to make new code for the Equals() override. Simply checking 'equals' for each variable within the struct sounds so easy that there has to be some kind of catch.
well if you want to check if they are IDENTICAL CategoryTag , like same values then yes thats what you do
but it would return true also if object is not the same
well not object, since its struct
{
Transform[] _Transforms = _Transform.GetComponentsInChildren<Transform>();
for (int i = 0; i < _Transforms.Length; i++)
{
T[] _Components = _Transforms[i].GetComponentsInChildren<T>();
for (int j = 0; j < _Components.Length; j++)
{
_Components.enabled = true;
}
}
}``` How do I do this? Component doesn't contain enabled
the override is basically pointless
so i don't see any reason for them to do it
but if you really want to
you can just create a unique hash from the fields
that you need to compare
(which in this case is all of them which is what it already does)
yeah was just thinking, struct doesnt have instance
Anyone have experience in changing a mesh filter of a player object. I'm trying to do a prop hunt effect. Here is the current code, using a raycast to get the object which is working. But switching the meshfilter of the player is not working It should just be be a Chair for the mesh filter.
Code:
if (Physics.Raycast(transform.position, transform.forward, out var hit, Mathf.Infinity, mask))
{
var obj = hit.collider.gameObject;
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
Debug.Log($"looking at {obj.name}", this);
Mesh mesh = obj.GetComponent<MeshFilter>().sharedMesh;
Mesh mesh2 = Instantiate(mesh);
player.GetComponent<MeshFilter>().sharedMesh = mesh2;
This is what the objects mesh filter changes into(it is supposed to be Chair)
Figured it out, Its because the mesh I was transforming into was marked as static š¤¦āāļø
Lol
Tried that. Many components apparently don't inherit from Behaviour and they break when you try to treat them like a behaviour
Character controller, mesh renderer are a few I tried. Camera seems to be one of the only things that actually worked with that.
by treat u mean inherit them from Behaviour?
I would get the component using GetComponent<T>() and then cast that to a behaviour
u probably need to inherit them from behaviour, might be annoying for overriding all default components u need, but im not sure if thats how u supposed to do this
I gave up. Instead of disabling them, I just deleted them using the script I showed
Override Equals, check other is CategoryTag otherTag, and if so return this == otherTag. If not return false. The point of Equals override is that it should return consistent result as == operator.
For HashCode simple way is return field1.GetHashCode() ^ field2.GetHashCode() ^ ā¦;. You can choose better way to combine hash to reduce hash collision, but it works as long as same object returns same hash.
Hi all. While creating a mesh by script, do I need submeshes to setup different materials/uv?
is it a bad idea to have lots of rendertextures around or does it not really matter until you hit some critical limit? I read about 200+ for certain mobile devices would cause crashes. I'm running the objects through a computeshader every update, and I'm just not sure I want to copy the pixels from a rendertexture to texture2Ds 50 times per frame instead of just setting RenderTextures as _MainTex in the shader.
I think it's just the memory usage that matters, which copying them to Texture2D won't help with, because you're not compressing them by doing that and they still need to be in GPU memory to be accessible to shaders.
hmm alright, thanks.
Hey, I've got an interface that need an ID attached to them in order to function correctly, however interfaces can't hold fields. Is there a best-practice solution to get something like a field into an interface? Currently I've got a property that I implement in the classes using the interface, which I don't want to rely on everyone doing.
Properties in interfaces is fine
Yeah but I can't put the backing field in the interface
Yeah but the implementing classes are too different to reasonably inherit from the same object
So basically I have
public int deckObjectID { get; set; }
in the interface, and then every class has to implement the getter and setter on their own
Which is a lot of duplicate code that I'd love to have in the interface, especially considering they all get their ID from the same supplier
but do u need to "implement" it, basically u just need to copy exactly same line of code, right? since get; set; will be already an implementation by itself
its not that bad
You should use a separate component to hold the ID for this system then
Unity thrives with composition rather than inheritance
These are not components on gameobjects, unfortunately
Basically they all need this, and also in their constructor they need to set the backing field correctly
i mean do u need that variable?
what if u use deckObjectID instead of it
u can use getter/setter as property itself
What are they then
Huh, I didn't know I could just re-declare the property with default get set and then that would be fine
Some of them are normal code-only objects, some of them are scriptableobjects
Then I at least don't need the backing field, which is slightly better
tbh thats a little weird to have one specific property in such different classes, no idea how u gonna use that property
Basically I have a custom collection I called a "Deck"
ye its basically 1 line of code per class, isnt that bad
I'm still working on it, but basically it's a set of dictionaries controlling the current state of that object
I want to be able to reliably control whether or not items in my deck are "available" to be rolled, locked, which means they have been rolled as an option but not claimed yet, or claimed, which means it's active in the game at the moment
I want to be able to o(1) get an item from the dictionary so every object needs to supply an ID, basically
huh?
i wouldn't overthink it. how many cards are in your deck
there is a reason KeyedCollection with multiple keys doesn't exist
It depends on the deck. I named it "Deck" but not because the contents are exactly "cards"
it is possible to author 100% correctly in typescript, but not 100% correctly in c#
well
how many
For the Item-deck it could be like, 100?
okay
For the hero-deck probably like 15
i don't think this optimization will yield much
100 items is very small
i don't understand what this is supposed to store
It's a custom collection so it stores a bunch of things
But with pre-coded functionality for keeping track of what has been "pulled" already
okay
Like if all of this was just in a list I'd need to manage that separately, probably for each type
hmm
you keep adding more and more stuff that makes it sound like you've veered off very far down Bad Lane
I may have
do you want to get out of the Bad Neighborhood
like, when a hero is rolled I don't want to be able to roll him again for the rest of that game
I'm hoping I can black box the bad neighborhood
or do you want to become a boss of crimes against programming
like build a giant wall around it
lol
and then I don't have to look into it so much
but that is so exceedingly simple, that there is definitely something i don't understand yet
is this like hearthstone's roguelike format?
Like, this is not a card game, but I want the randomness to work the same way as a card game does
like whatever it's called
Card Game Roguelike Where you Go Up A Tower and there's Poison
like let's say you pull 3 cards, you pick one and the other 2 go back in the deck
and when a card is pulled, it can't be pulled again
but this is not a "card" game
well what kind of game is it
and I want many different things to follow that same randomness pattern
it's closer to an RPG, but the games are shorter
you win or lose in an hour or two
okay
you mean it's classic final fantasy style combat, and you're pulling encounters from this deck?
is that the idea?
and the game world is pre-set with items and monsters in these decks that run out over the course of the game
It's not classic ff combat, but I am pulling encounters from the deck
that makes sense okay
and items, and which characters show up, etc
so you want to have a Discover mechanic too right?
Yeah
okay great
like "Show me 3 healing items and let me pick one of them"
I implemented my own collection for it
so where does the initialized list of monsters and items for this playthrough live?
in a List?
which takes care of all of this generic pulling, locking, "shuffling" etc
Well, right now it is in a dictionary
because I wanted to be able to remove a specific instance of a "card" so to speak
yeah
that has made things way harder
a deck is a list not a dictionary
which is okay
you are reimplementing a list on top of a dictionary right now
I am not overly worried about looping over the keys etc
randomly getting a key index
However, each item needs to know its own key
why?
well, otherwise how can I know which item to move around
basic equality checks
It just.. seems wrong to directly compare a complex object
why? the references will be the same
it won't be complex at all
You're saying I loop over my list to find the current object and then move that, right?
sure, or whatever you need to do
yep, that will Just Work
I'll still need my subclasses for this deck though
as they have different types of discovery
create different methods
but it does get rid of the ID part
don't make multiple classes
you don't need them
just make differently named methods for discover
i'm writing the example hold on
This is a Deck<T> at this point
it might not be necessary. you don't actually need to know anything about the T
so Items can be looked up by their complete name, their item tags
i mean of course it's a collection, you can have it be T
that's find, but then have a class MonsterDeck : Deck<Monster>
don't do new Deck<Monster>
but you won't really need to do that. you can put those methods anywhere. hold on a sec let me show you an example
For stuff that requires no extra functionality I just use Deck<T>, and then for Items for example I use ItemDeck<T>
no
just do MonsterDeck and ItemDeck
like i'm showing
that implementing the concrete type
generics are not for extending behavior, they are for collections and that is all
if it's an ItemDeck, it's an ItemDeck, not an ItemDeck<T>
it's not an ItemDeck<Potion>
it's a PotionDeck
you can have an ItemDeck<T> as long as it is abstract
but i think that's a bad idea
just put the methods
that have to deal with these things somewhere else. not in the collection
it will be too confusing to put it there
But, would you have these inherit from Deck?
public class ItemDeck<T> : Deck<T> where T : GameItem
As it is it's only an ItemDeck<T> so it can extend Deck<T>
here's an implementation of a deck
sealed class Deck<T> : IReadOnlyList<T> {
private List<T> entities = new();
public Deck(List<T> startingEntities) {
entities.AddRange(entities);
}
public void Shuffle() {
// shuffle the entities array
}
public List<T> Draw(int quantity) { ... }
public void ShuffleInto(List<T> cards) { ... }
}
// elsewhere!!! the smarts of this is interacting with the UI
Deck deck;
public async UniTask<T> Discover<T>(int count) {
var drawn = deck.Draw(count);
var chosen = await GameController.instance.userInterface.ShowAndChooseFrom(drawn);
// now not drawn
drawn.Remove(chosen);
var notDrawn = drawn;
deck.ShuffleInto(notDrawn);
return chosen;
}
Because all the rolling, locking etc of items is done one time in Deck, but sometimes I need access to stuff in GameItem etc
IReadOnlyList?
you don't have to use it if you don't want
it won't matter
because all deck needs to be aware of is whatever is in common with monsters and items. which should be the base class of items and monsters
Right, but the reason I am using T here is because they have no shared base class
except for like, Object
then it's an object!
they are fairly far apart
Right, but then in a subclass
like, ItemDeck
I want to be able to access item-specific discovery
like discovery based on effect
or rolling an item based on rarity
the problem is that it causes all of your methods that operate on this, in interesting ways, to become typed in a way that is useless to you
what do you mean?
it's hard to explain because you have no experience in this and i have a lot
just Write a Method to do that
like don't overthink this
of course you can use generics
but don't put this functionality of rolling an item based on rarity
into the Deck class, or any subclasses of it
write the method Anywhere Else
does that make sense?
Right, but that is the thing I wanted the deck to do..
because you're going to have only one instance of an ItemDeck
sure
In some manager class
but then in a sense, this deck is that manager class
the item deck is the manager for items
it's the "item manager", right?
no
okay
look at my example
look at Discover
do you see the problem with it right now? the problem was introduced by adding <T>
Yeah, your deck is more of a pure container
no
Deck deck;
public async UniTask<Entity> Discover(int count) {
var drawn = deck.Draw(count);
var chosen = await GameController.instance.userInterface.ShowAndChooseFrom(drawn);
// now not drawn
drawn.Remove(chosen);
var notDrawn = drawn;
deck.ShuffleInto(notDrawn);
return chosen;
}
versus
Deck deck;
public async UniTask<T> Discover<T>(int count) {
var drawn = deck.Draw(count);
var chosen = await GameController.instance.userInterface.ShowAndChooseFrom(drawn);
// now not drawn
drawn.Remove(chosen);
var notDrawn = drawn;
deck.ShuffleInto(notDrawn);
return chosen;
}
what becomes way more complicated because of <T>?
this should illuminate why you need an Entity - you can have something else, but the alternative is way too nuanced to discuss right now
Ah, but the actual UI part of this wouldn't be in the deck
i know!
it's not
this is "somewhere else"
it doens't matter where it is
but that's what's valuable
and do you see
like writing the collection manipulation logic takes milliseconds
writing the UI is painful
Basically right, I need the base class Deck to work on all types
and because you introduced T, ShowAndChooseFrom<T>(List<T> listOfAny) becomes way more complicated than ShowAndChooseFrom(List<Entity> cards)
you need a base class for your items and monsters
and 99% of the time, your UI will not care if it's an item or a monster. it will care what it should show where
no, in deck, treat everything as an Entity
and make a sealed class Deck<T> where T : Entity if you want to have specialized collections
a lot of people make this mistake
they think about the collections being specialized and adding functionality
you'll notice in the CLR there is no ListForItemsThatAreCards<T> : List<T>
that's just not what generics are for
it feels like it's what they are for
they're not for grouping a bunch of methods together. do that somewhere else
put it in your game manager
Hm
it makes sense for the deck to have a shuffle method
but also, it does not. trust me. in my game, i don't have Shuffle in Deck
It also makes sense for the deck to have a draw random method right
no
like what would you have in the "Deck" at all?
for something like hearthstone, just additional data about the deck
if I take away the draw, the discovery, the specialized functionality, the search
right but this is not a card game
the "Deck" is specifically there to be a collection of functionality
is that people will do stuff, like use an item, that changes the rules
something like Shuffle is tightly coupled to the rest of your game
regarding randomness for objects as if it was a card
for example, you might have an item that skips shuffling, or an item that lets you keep all three items you discover, etc.
Right but as I said this is not a card game
this is only randomness as cards work
as opposed to say how dice work
yes, and i am saying, actually, all these games have tightly coupled functionality
if you roll 1 on a dice, you can roll 1 on your second dice
you will wind up with the deck having to peek at the item - this is a problem you ALREADY have
which it shouldn't do
but if you pull the ace of spades, you can no longer pull the ace of spades, right?
that's just specific to your game
i'm saying the kind of game you're making
you will wind up having items and monsters or other stuff
that will make 1 change to the rules
that will require an invasive change to your Deck class
Right but none of those rules can be "prevent shuffling"
because the deck isn't there to "be shuffled"
it's not an actual deck of cards that are say, pulled each turn
maybe it' snot shuffling but it can be many other things
the key problem you came here with is using a dictionary instead of a list
Sure
you actually have everything else under control. don't declare a Deck class at all really
and it is probably better to do a list
just use a List
and any specialization, write a method somewhere else. in GameManager
But I need a bunch of different objects to then control the randomness
you just remove items from a list
right but then the cards that are not chosen have to be put back
i mean, we can talk about how to implement that with a list
it's pretty easy
well
i showed you a Discover implementation
Sure
here it is with a plain list
Right, but in terms of our "decks" I have very few of the variables in yours
the deck has no descriptor, no name, is attached to no player or hero
it also has no ID
public async UniTask<Entity> Discover(IList<Entity> deck, int count) {
var drawn = Draw(deck, count);
var chosen = await GameController.instance.userInterface.ShowAndChooseFrom(drawn);
// now not drawn
drawn.Remove(chosen);
var notDrawn = drawn;
ShuffleInto(deck, notDrawn);
return chosen;
}
then you don't need a Deck
Right, but having all of that stuff in a game manager
controlling how to draw items, events, heroes, monsters, etc
becomes a very big game manager
i don't know what to tell you
and it's not even the main part the game manager would do, right?
these games are complex
It seems like the name "Deck" confuses it
it's really a system for controlling the randomness
not at all related to actual cards
you can make something worse, that takes 5,000 lines and distributes it int hte wrong place, among 20 files, that have to invasively know about everything anyway
and then you wind up with 15,000 lines
merely following the same pattern of randomness as a deck of cards would
anyway this is my perspective, i have a lot of experience in this. ultiamtely you are leaning on
the psychological ickiness of looking at a file from a mature, complete game
and I wanted to separate this functionality out into its own class specifically controlling that
Well, it's a question of "where do I put it" right
it definitely could go both places
if you have any spell like functionality in your game, i am telling you now, it is very invasive
like imagine that I am making world of warcraft right
it IS part of your game rules
and instead of a loot table, I would use card-like randomness
I would not put this item rolling functionality into the game manager, right?
i think it's the best place to put it
Even though it could be there, I would probably separate out everything related to rolling loot into its own file
for the same reason that basically every collection type omits functionality like this
so it would be Deck that just constantly refers to "Object"
Yeah, thanks for the input
you don't necessarily need Entity, you need Renderable
renderable?
and you also need HasId
yeah because you're going to have a method in your UI
that takes a thing and tries to show it on screen
sometimes it's an item and sometimes it's amonster
Ah, no, these do not go on screen as-is
and all the hard part of making a discover ui is showing the three rectangles and setting up the event handlers and doing the animation
hmm
as they are not actually cards
they go backstage
it will help me give you more specific examples
Sure
Basically I have UI elements that are fed backstage objects
it will look like this
if you imagine it was a card game and was hearth stone, I would have the "Card" and the "CardEffect" as separate objects
the "Card" would be the UI object and when it is fed the backstage-object it sets its data based on the backend
and that is how most of the things work
so none of these are monobehaviors and none of them are "physically in the game" so to speak
although some of them are scriptableobjects
maybe the only way to truly understand why you should make your 5 discover methods in your game manager
is to go ahead and try to finish a game where you start by writing them in a deck class
for example, you might have a monster whose behavior reacts to what card was drawn
you'll eventually achieve this by firing a DiscoveredCard event
That makes sense if it was a card game
and that should illustrate a concrete example of how a Deck class would have to be invasively aware of the rest of the game
listen i don't play wow, so i can't give wow examples
lol
but you gotta work with me here
But there's no way for a monster to react to a drawn card
a monster isn't a "card" any more the second it leaves the deck
in that sense
it's only a card in the nature of "being drawn"
and being searchable, and being limited in quantity
well i think you can imagine
you want some behavior in a monster
that interacts with literally anything else in the game
you'll need an event system
Like, if you want to simulate the randomness of dice, you Random.Range(0,6) right?
that gives you basically perfect dice
but if I want the randomness in cards, I can't just go Random.Range(0,52)
one perspective is that 99% of these games are interesting because they innovate in the "card text"
Yeah but my game is not a card game
so a monster that reads "all your dicey dungeons dice come up as even numbers now" is interesting
I don't have these cards on my hand and then play them on the field
all of these games are card games. WoW mechanics are routinely prototyped as card games
because they're all spells
it's just text
it's some game rules and they're interesting
it's, when you roll a random thing, it should behave as a card
i know it's not a Card Game but it is a card game
it's true for real, blizzard does prototype its games with cards
Like, the moment the rolling is done it ceases to be a card 100%
Sure
i'm saying there's text written on the monster right?
it has some rules
i mean, it will eventually, to make a more interesting game
it casts fireball, fireball is a spell
whatever
and fireball has some text
Sure, so I have items that do things and you could call it a card if you wanted to
yes
things like teleport character or heal character or whatever
right exactly
but none of these things interact with the drawing of cards
no, because it's not a card game in that sense
because 100% of your game is going to look like that
anyway that's it, that's my perspective
you can poke around the spellsource repo, literally thousands of cards, and see how card text is implemented
because it's how a lot of these games wind up looking
You ever play uh... Xcom?
yes
xcom is definitely architected the way i am describing though
you roll 1/100 and then check against your hit chance
the randomness is dice-randomness
imagine if instead you did the randomness through cards
xcom is really supporting my case
the rules for card-randomness is:
A card exists only once.
The order of cards matter.
right?
for example, "immune to being critically hit (unless flanked)" is an ability
Sure, but that's unrelated to the randomness
Right, but that's still not related to the type of randomness
well like i said, this function you are worried aobut, it's very small
the random dice part is 4 lines. and by the way, it is invasive
But do you understand what I mean by random type?
because i have to store the seed somewhere
and i'm not going to store it in the deck
he can only crit once
that doesn't make it a "card", but it changes how his randomness works
he can't roll crit 3 times
so you would have to invasively populate the Deck class with references to a Random class instance
every not-crit increases the chance that the next one is a crit
i think i finalyl gotchyu
Well it is the whole point of the class
like let's say I have a huge table of items and I just roll which item to give right
yes, but it will have an instance of Random with a seed right?
i think i got you
i did it
Uh, I use the static unity random
i mean you can not use a seed
which is pre-seeded
well that's a mistake
all these games have seeds
that are carefully controlled
even randomness is invasive!
look i'm trying to make your life easier not harder
it turns out everything is invasive in a video game like this
maybe. anyway good talk
so, the "seed" is gone in that sense
i gotta go
Yeah thanks for the help
i think the game will be fiun
I appreciate it
I will try to show you when the randomness thing works as I want it to
okay what about "this monster always gets drawn first in a playthrough"
"this monster always appears in a discover"
"until it is picked"
If there was such a thing that would be in the game mode

Like the game mode would specify the starting conditions anyway
it would mean some part of the random drawing would have to invasively know about the items inside the deck
okay what about
"put a monster into the deck that always appears in discover until it is drawn"
it's a monster called Corruptor and it puts a corrupt blood into your encounters pile
this is actually a really common mechanic across all these games
sure
If I roll a dice and get a 6, what is the chance that the next roll is a 6?
"Next time you choose an encounter, one option is always replaced by Corrupt Blood until you choose it"
yeah yeah yeah
i'm just trying to illustrate that you can call the method "PickEncounter" or whatever, and it will invasively have to know a lot about everything
your actual deck class can have the shuffle methods or whatever, it can be simple
that stuff isn't hard to write
you can move those methods if and when you need to invasively know about something when you shuffle
but it will
i already know it will
knowing nothing about your game
moving things will be easy
But you're still attached to cards as cards, not as a system for randomness
Again, consider dice
sure when you roll dice
rolling dice will evnetually need to invasively know about something
okay i gotta go for real
Rolling 6 does not affect the chance of rolling a 6 again
Pulling an ace changes the chance for pulling another ace
And that behavior is the point of the deck.
briefly read through this discussion - if the purpose here is simply to act as a random number generator with certain properties, why not use it like that and keep it simple - use a mediator that assigns values arbitrarily as needed, your generator logic only spits out a random number, and your mediator returns the object it assigned the id to
I suppose you can compress all of that into a generic Deck<T> object, but the key point is the objects you provide aren't having to supply their own ids, nor keep track of their own id
I went over to the "directly remove the object from a list by equality comparison" as suggested by doctorpangloss
so the ID itself has been removed, as has the need for an interface
This would work, but sometimes I want to get random objects by properties like "Find two random healing items" or "Find a hard encounter"
So what is your issue now? @frozen badger
I am doing better now, Just ended up in a somewhat winded discussion
I got rid of the ID, but kept the <T>
yeah, didn't mean to dig up an issue again as it seems like you've already resolved it - mostly just my own curiosity in how to handle it
Yeah I read through it now. It looked like you had 2 completely unrelated conversations going on there near the end.
I mentioned it but I think the word "Deck" may have alluded to a card game that didn't exist and caused confusion
it was more "Deck" as in the data structure
I don't believe that was the issue. From my prespective doctor just tried to explain to you that manipulating a collection should be done from the outside. That the API of whatever data structure should only contain elementary operations and nothing more. Everything that has multiple effects on a particular data structure should probably not be declared as part of the API. In this case he gave multiple great example of where adding Discover method as part of a deck is a bad idea because it causes the deck to have to emit events etc... instead of it being done from some game manager type class