#archived-code-advanced

1 messages ยท Page 72 of 1

brisk spruce
#

Overall what I see is what looks like the parent is passed into methods of the child which is usually a code smell that something funky is going on

obsidian coyote
#

the thing being passed in is treated as a readonly object, it isn't being updated by the other classes

brisk spruce
#

Its still a parent being passed to a child, which is usually a sign something is upside down

#

theres probably a way easier way to do what you want, and usually in some way or another it means inverting your logic upside down from what you have atm

obsidian coyote
#

for example, the healthbar sits as a child of the canvas, and updates its display whenever the tank that caused its instantiation's health changes

brisk spruce
obsidian coyote
brisk spruce
#

That is indeed exactly as I said, that 100% is a child mutating the parent

#

it just looks like subscribing to an event... but that counts as a mutation

#

and thats a big code smell

obsidian coyote
#

i guess, but its decoupling the rendering of the healthbar from the the tank in this case

brisk spruce
#

Nah you are now tightly coupled to specifically being a health bar for a MiniTank and you cant be a healthbar for anything else

obsidian coyote
#

i dont follow

brisk spruce
#

You cant pass in something other than a MiniTank or derivation of that to Init(...)

#

owner cant be anything but a MiniTank

#

Youve tightly coupled yourself to the parent

obsidian coyote
#

yeah, thats true, but i could convert that to a generic type if i wanted to, but in my case its not needed

brisk spruce
#

Or... you could not tightly couple to the parent at all

#

Why doesnt MiniTank handle mutating the health bar instead, Parent -> Child

#

Specifically, show me the code where you invoke OnTookDamage

obsidian coyote
#

this is in the mini tank class

round wharf
#

sadly not

brisk spruce
#

What I am expecting to see is

OnTookDamage?.Invoke(this, New FooEventArgs(...));

Or whatever

#

Where do you have the actual event being invoked

obsidian coyote
brisk spruce
#

There we are...

Why not just have the code that modifies the health bar right there

obsidian coyote
#

because the healthbar isn't guarenteed to be attached to the tank?

brisk spruce
#

Whats the issue? If it has a healthbar, modify it, if not, no problem

obsidian coyote
#

also its NOT a component of the tank or a child for that matter

#

so its a pain to "find"

brisk spruce
#

Thats fine

obsidian coyote
#

since it exists on a totally seperate game object who's lifecycle differs from the tank

brisk spruce
#

You should have some kind of core "service" that knows where the health bars are in some way

#

But it looks to me like all your woes are stemming from this heavy coupling of Child->Parent you have done, and having children mutating their parents which is a very fast route to spaghetti town

obsidian coyote
#

i guess i just don't see why i would want to have to find the reference to the healthbar each time i want to modify it since caching it on the tank is pretty simmilar to just subscribing to an event the tank emits ๐Ÿค”

brisk spruce
#

In terms of if you have to find it each time, that depends on if we are talking about numerous healthbars or 1 that is always the same

#

But overall I prefer storing all this data that matters not on my monobehaviors, cause you run into all these sorts of weird issues where you have to figure out "who" or "what" is your "source of truth"

obsidian coyote
#

currently the intention was that the health bars will return to a pool when they are not in use (tank is offscreen), then they are pulled from the pool whenever they are needed again, and that can mean they are assigned to different tanks each time

brisk spruce
#

I prefer storing all my "matters" data in a single source of truth that everything else mutates and listens for changes on

obsidian coyote
#

this way if you have like 200 tanks, but only ever happen to see like 20-30 of them, you wont have 200 healthbars in memory

brisk spruce
#

I dont think a healthbar MB should care who its assigned to, and it should literally just have simple mutation methods on it, like:

SetMaxHealth(int maxHealth) { ... }
SetHealth(int health) { ... }
SetVisible(bool visible) { ... }

And then exposing the Transform prolly so you can modify that

#

And then the service tracks the relationships of Tanks <-> Healthbars, and you can do stuff like:

HealthBar HealthBarFor(Guid tankId) { ... }
HealthBar AssignHealthBarTo(Guid tankId) { ... }
void UnassignHealthBarFrom(Guid tankId) { ... }
void RedrawHealthBars() { ... }

etc etc

#

Tanks shouldnt care about their health bars, health bars should care about their tank, the service operates "overhead" controlling that stuff, etc etc

obsidian coyote
#

you'd still need to be able to force the update on the health bar whenever something on the tank changed that the healthbar needs to relay to the user

brisk spruce
#

So chances are TankService injects HealthBarService, and Tankservice can call methods to update the values of Tanks health and tell the healthbar service to redraw at the end if anyone has changed that matters

obsidian coyote
#

would it still make sense to decouple the various services to the components they relate to, like a healthbar service for healthbars, etc ๐Ÿค”

brisk spruce
#

Nah its fine for HealthBarService to be tightly coupled to the Healthbars, since that is its "job" so that makes sense

#

This is my example pic of the stack I use that keeps everything super organized. I have been falling in love with this the more I use it, everything feels so smooth to implement

obsidian coyote
#

hm ill have to give that a shot, always open to try new things ๐Ÿ™‚

brisk spruce
#

and a link to my git repo showing the example project

obsidian coyote
#

cool, ill check it out tomorrow, getting late here

plush narwhal
#

so there is no way I can do this without converting the method to a task?

tiny pewter
#

task.run return you a task

#

so you await it to get its result

plush narwhal
#

rip, I'll just make two seperate methods

harsh canyon
#

Hi

#

I have a state machine for my enemy ai, it goes like this, Find Cover -> Take Cover -> Shoot Player -> Take Cover (repeat)

#

but i want to make a slight modification to it (for another enemy type)

#

so it becomes

#

Find Cover -> Take Cover -> Rush Player

#

with my current architecture, I would need to duplicate a lot of code in order to make this work

#

how can I design my state machine so it is more open to modifications

plucky laurel
#

are your states not abstracted?

harsh canyon
#

they are

plucky laurel
#

can you show a sample of how you construct the fsm

harsh canyon
#

sure

#

this is what all states derive from

#
public abstract class EnemyBaseState
{
    public abstract void EnterState(EnemyStateManager enemy);
    public abstract void UpdateState(EnemyStateManager enemy);
    public abstract void ExitState(EnemyStateManager enemy);
}
#

for example here is the find cover state

#
public class EnemyStateFindCover : EnemyBaseState
{
    public override void EnterState(EnemyStateManager enemy)
    {
        int ind = Random.Range(0, enemy.CoverPointsSet.items.Count);

        Vector3 point = enemy.CoverPointsSet.items[ind].transform.position;
        enemy.AgentMoveTo(point, 0.5f, delegate
        {
            enemy.SwitchState(enemy.StateTakeCover);
        });
        
        enemy.CoverPointsSet.Remove ( enemy.CoverPointsSet.items[ind] );
    }

    public override void UpdateState(EnemyStateManager enemy)
    {
        
    }

    public override void ExitState(EnemyStateManager enemy)
    {
        
    }
}
#

the problem isnt with creating new states or logic

#

its with changing the structure of the state machine

plucky laurel
#

show a sample of where you construct the fsm

harsh canyon
#

like if i wanted to create a new enemy type that just rushed the player

#

here is a snippet from state manager

#
    private void Start()
    {
        _currentState = StateFindCover;
        _currentState.EnterState(this);
        DisableRagdoll();
    }

    
    private void Update()
    {
        if (!_isAlive) return;
        
        _currentState.UpdateState(this);
    }

    
    public void SwitchState(EnemyBaseState state)
    {
        _currentState.ExitState(this);
        _currentState = state;
        state.EnterState(this);
    }
plucky laurel
#

so construction is not abstracted

#

consider the following

class FSM {} ^ what you have above but state agnostic

class EnemyType1
{
  void Start()
  {
      this.fsm = new FSM();
      fsm.AddState( new StateFindCover());
      ...
      fsm.SetState(fsm.States[0]);
  }
}

for example

harsh canyon
#

oh i see

#

but what about the state transitions

#

for example in my state FindCover

#

after finding cover it transitions to TakeCover

#

so these states are tied together

#

but lets say, after finding cover i want it to rush the player

plucky laurel
#

two options, you either allow states to switch states

#

or you abstract the transition itself

#

first is simpler all you need is to have access to the root fsm in your state base class

#

second is the "proper" way that makes an fsm and fsm

harsh canyon
#

yeah abstracting transitions is what i have been thinking about

#

but i just have no idea how to implement it

plucky laurel
#
class Transition
{  
    public Transition(State from, State to, Predicate condition)
}
harsh canyon
#

i guess these transitions i would need to store in the state manager, as opposed to states themselves?

plucky laurel
#

or

class State
{
    List<Transition> _transitions;
}

void Start()
{
    fsm.AddState(new StateFindCover()).AddTransition( .. );
}
plucky laurel
harsh canyon
#

okay

plucky laurel
#

you shove stuff in, it does things, its a machine

harsh canyon
#

I am gonna try your suggested approach out and see how it goes

#

thanks

real blaze
#

any Unity UI layout technique to achieve this sort of layout?

#

Unity's default Grid Layout sucks

hearty trellis
#

The component name is GridLayout

real blaze
#

That doesn't do that

#

that works like this

hearty trellis
#

Did you try the Grid Layout Group

#

I tried it just now and it works

real blaze
#

that's not what I described above

hearty trellis
#

oh I just noticed sry.

real blaze
#

no probs mate โฃ๏ธ

hearty trellis
#

๐Ÿ‘

#

can you help me?
Im having a problem with my NetworkRigidbody.
Im using Unity Version 2022.3.5f1 and Netcode for Gameobjects 1.4.4 . I have one Player prefab with my Movement Script and a Network Rigidbody. On the host side everything works and the Rigidbodys are isKinematic = false but on the Client side its isKinematic = true. I dont know why. I tried to set the IsKinematic in the Await or the OnNetworkSpawn but both didnt work.

scenic forge
#

If so it's trivial to write one yourself, otherwise yeah it's going to be iffy.

real blaze
real blaze
#

saves as data

#

but has a button that makes gameobjects for editing, and then another button that reads those game objects into these dats

#

(light mode warning btw)

scenic forge
#

Should be pretty trivial to calculate where the children should be, given all the necessary information (container size, child size, gap)

real blaze
#

oh wait, you mean it's pretty easy?

lost dome
#

This is a weird one to choose the channel for as it is about animation but the problem I'm having is related to script.

PROBLEM
after switching the player model animator only works after manually interacting with it or saving and then compiling a script.

CODE- https://hastebin.com/share/xucaferora.csharp

scenic forge
real blaze
# scenic forge Yeah.

if it were just math, I'd do it. but Unity's UI Layout system has it's own public and internal APIs you have to follow if you want all the other layout components to work effectively

scenic forge
#

๐Ÿค”

#

I mean that you are doing the grid layout yourself and not using any UGUI stuffs, so those shouldn't matter to you?

#

There's nothing stopping you from manually setting where each child should be, and not using any layout components at all.

real blaze
regal olive
#

Question: I'm planning on implementing a driving system into my game, and I actually want my player to open their car door and climb inside when interacting with the vehicle. I can easily set up animations and scripts for the vehicle, but my question is how would I go about the implementation of the mapping of the player's hand to the car door to open it, as well as mapping the player to properly sit inside the vehicle?

dusty wigeon
regal lava
regal lava
#

or just write your own script to add the margins in per row/element

vale zenith
#

In Profiler, i have a lot of time spent in "Other" category, but nothing in hierarchy says exactly where. It just lives in the "Self MS" category of PlayerLoop (top line in hierarchy)

Does this mean some random script is probaby slowing it down?

I have no animation, AI, particles, neworking, loading. I have like 5 audio sources but that's only utilizing .5% of audio CPU

dusty wigeon
vale zenith
#

It's in a build

dusty wigeon
#

Show a screen shot

vale zenith
#

See there is stuff in "Self MS"

dusty wigeon
#

You have FPS limit

vale zenith
#

I know

#

Let me show you a "normal" frame for comparison

#

See, nothing in "Self MS"

#

on PlayerLoop line

dusty wigeon
#

And what is the issue ?

tiny pewter
#

have you tried to turn of all gameObect and profile a empty scene?

dusty wigeon
#

Because, in either scenario you are hitting your target frame rate

vale zenith
dusty wigeon
vale zenith
#

Which isn't really too helpful tbh

dusty wigeon
#

My point is, what are you investigating ?

#

I understand that you want to know what is being done in profiler loop. However, I doubt it really matters.

#

I can help you with trying to find performance gain, but I do not know any things about the self ms of the playerloop

vale zenith
#

That's ok, there doens't seem to be much info on this Self MS in PlayerLoop thing. That's why I'm asking around.

It just concerned me that in a Scene with only my scripts running, I'm getting these random 3ms delays the profiler doens't seem to help me interperet, which I thought was largely the point of profiler

dusty wigeon
#

No idea how it can be relevant

#

What do you mean 3ms delays ?

#

You are hitting your target frame rate

vale zenith
#

That is a test scene with 0 graphics. But if I'm targeting 72fps or higher down the road (it's VR), random unexplained 3ms spikes can start becoming a headache?

dusty wigeon
#

Then, investigate.

#

Also, did you try the deep profile option ?

#

It might be able to discover more.

vale zenith
#

Yeah I do have deep profile on

dusty wigeon
#

And, did you look at the timeline. Sometimes there is other things happening in the job system

#

And, at the end of the day, the profiler is not the perfect tool.

#

You better use native tooling

#

If you want the best accurante information

vale zenith
vale zenith
dusty wigeon
zenith panther
#

Hi everyone I really need some help, how can I go about doing a melee combo system with the input system? I've tried many methods and none of them seemed to work for me

dusty wigeon
#

You need to add a layer on top of it. Such as tracking what was the latest attack done, what attack can be done next.

polar widget
#

@zenith panther exactly what @dusty wigeon said* . The inpiut system is responsible only for telling what is the player inputing to your game

A combo system need to be separated & custom to your own needs , if you need pointers give us more context on what exactly you are trying to do ๐Ÿ™‚

zenith panther
#

I understand! So I want to make a simple combo system for a hack and slash game as I'm doing a challenge with a friend, the combat I was taking reference to devil may cry with its melee combat, thats kinda where I'm going for it

#

So I want it to go like idle hit 1 > hit 2 > hit 3 > idle, something like that but I've just not been able to do it yet

dusty wigeon
zenith panther
#

I'd say I'm intermediate, I'm not an expert in it but I know common knowledge for it

dusty wigeon
#

How well do you understand ScriptableObject ?

zenith panther
#

I'm not familiar with polymorphism, as for scriptable objects, I know a little bit of it

#

I would have asked this question in code general but it sometimes gets missed which is why I went here

dusty wigeon
#

Then, you should learn more about polymorphism as it is one of the most important concept of coding in Object Oriented Programming. It is also a most for what you want to do.

ScriptableObject is also something that would be really useful as it would enable you to create "Definition" of what a combo is. By example, you could define, that this particular weapon holds 3 attacks that each diverges in others.

#

There is other ways, however, I believe this is the best way to achieve a modular and complet "combo system".

#

(There is hundreds of tutorial)

zenith panther
polar widget
#

@zenith panther the most important thing you need to learn is how to have the state & the good data so you can apply the logic that you want ๐Ÿ™‚

#

In your situation you can start by doing a simple proof of concept that have a list of event you recieve from your input system.
And use it as a "Pile" when the first one is done , you remove it from the pile & play the next one.

Then you add conditions : Like A can't combo after D but can after B & E , etc ...

#

one by one for example. it's def not the best way to do it because it will be hard to scale but that should get you started to try different stuff to get to the point you want to go.

zenith panther
#

Thank you! All of this is helpful stuff for me to learn, I do appreciate it ๐Ÿ™‚

regal lava
#

So, I've been refactoring a bunch of code lately, looking for better ways to access scripts with limited dependencies. For example, your player has an inventory and an equipment object class. The inventory keeps track of the player character's general storage and the functionality of picking up and dropping items, while the equipment class contains info for what items are currently equipped to the character. Now, my problem is trying to understand the best way to cross reference these classes for when I want to take an item from my inventory, and equip it to my equipment class.

Early on, I felt like I shouldn't really expose the whole class to each other since I only needed to access a little amount of functionality between the two, so I thought about just subscribing to events to access those methods. However, as the project grew, so did the amount of events I needed and it quickly became more extra code to write than I wanted.

Next idea was to forgo the subscriptions and just expose the whole references to each other. For the most part, this works pretty well as long as I just don't touch stuff I'm not supposed to. It just seems like focusing too much on accessibility created more work and problems than I needed, especially considering that we can't assign data into a mono's constructor. By its nature, we're heavily encouraged to use a dependency injection approach, and with that alone makes it hard to limit what data can be accessed.

With that in mind, I feel like perhaps it's better to go heavier with a service locator approach, such that all objects that my player references, too shall have a reference to the service locator layer (the player in this case). This would mean that classes like inventory and equipment will still be referenced by the player, but for them to access each other, they will instead reference the locator and go down the reference tree. This could be done by a static (singleton) reference, or by sending a parent ref into each class.

brisk spruce
#

service locator approach
wuh oh

#

Most of the time thats an anti-pattern and has better ways to do it :x

polar widget
regal lava
#

A lot of the networking libraries use a similar approach is to why I've got this idea in mind. ;)

brisk spruce
#

I have a pic here somewhere, one sec

#

I wont say its the best way, but boy does it feel smooth and easy to implement everything once the boilerplate is complete

regal lava
#

Ah, that does seem pretty interesting. I think someone else was trying to sell me on a similar approach.

dry bear
#

Hi, could someone explain to me how to build Steam's GameNetworkingSockets for Android?

#

I've been trying to do it for days and it's being extremely difficult โ˜น๏ธ

dusty wigeon
regal lava
#

Inventory Slot, Equipment Slot, Ability Slot, Hotbar Slot

#

This is more an example anyway as I've other issues with controller needing events to the equipment class to equip the item when selected.

#

So again, more cross references despite the player owning all of these objects

dusty wigeon
#

Would that represent correctly the situation ?

regal lava
#

Yeah, not too sure about the slots there however.

dusty wigeon
#

I thought you said equipment has equipment slots

regal lava
#

Right, inventory would have slots too in this case ;)

#

I've a general base type slot which each of these systems inherit

dusty wigeon
#

Alright, so the issue is the relation between inventory, equipment and player ?

regal lava
#

some covariance garbo to make hotbar work with types

royal shore
#

Hello if I have a bunch of planes which are my floor tiles and I want to create one big mesh collider the shape of all of them together how would I approach this? is there a way to group all these mesh renderers and gameobjects together to create the mesh collider?

#

or is there some asset that already does this?

dusty wigeon
#

I see no particular issue in the relation they have.

#

What you do not like ?

#

Because it is pretty straighforward

dusty wigeon
#

Equipment does not know anything about the player.
Inventory does not know anything about the player as well.
Inventory does not know directly about the equipment as well.

regal lava
#

I guess my complaint is just in an expanding project, I'm feeling like I am cross referencing too much, and it's obviously because of implementation of stuff I did not have planned at the start.

dusty wigeon
#

You might struggle with interfacing correctly.

#

Do you use interface ?

brisk spruce
regal lava
#

As like I mentioned, my controller class needs a reference to the equipment, so now I've a reference over to that from that class. I've lesser scripts which need some relevance in these systems to keep them happy.

brisk spruce
#

My general rule of thumb I follow is: if its not something that conceptually exists "in" the world, like it doesnt have a scale/rotation/position or a sprite... I dont put it on my Monobehaviors

dusty wigeon
#

Everything you just describe to me is the ideal scenerio

regal lava
#

Yeah, honestly from just that it seems fine, but I do have smaller scripts like modifications to the character which needs to be cross referenced to the abilities, equipment, stats. Just like, these lesser but more numerous features I'm implementing.

dusty wigeon
#

Maybe those are the issue.

#

Elaborate on it.

#

If you open an ability what are its reference at the moment ?

regal lava
#

Perhaps, but I've actually building this large trigger system for character events, trigger when hit, trigger when attacked, trigger on cast, cast on interval

#

this applies to the neutral state of the character, as well as abilities that can cast

#

global modifiers you can think of

dusty wigeon
#

So, the abilities controls the character ?

regal lava
#

abilities and items do need to know about it, especially when you equip something

dusty wigeon
#

Why so ?

#

They need to know about what ?

regal lava
#

well, let's say you have a trigger on hit -> cast fireball, but you dont just want to cast a level 1 basic fireball, you want it to be modified by gear and other modifiers

dusty wigeon
#

Oh, so an abilities is affected by modifies which can be in an equipment or directly on the player ?

#

I still do not see an issue.

regal lava
#

so there's this large subscription system I got which helps keep mods updated, and caches when equipped.

dusty wigeon
#

See how I just push everything down

regal lava
#

Yeah, that's what it's looking like

dusty wigeon
#

There is no issue there

#

It is still the ideal scenario

#

Extract what is the source of the reference to something else.

#

Equipment has a reference to the player because the player has modificator.

#

Extract the concept of modificator

regal lava
#

So, for the controller that you need access to give input to these classes, where would you stick that

dusty wigeon
#

Who needs input in this situation ?

#

The abilities ?

#

Or only the player ?

regal lava
#

Abilities, equipping

dusty wigeon
#

Why does equipping needs input ?

#

The UI will manipulate an equipment

#

But never the equipment will listen to input

#

Am I wrong ?

regal lava
#

True, just if you've a statemachine with abilities and such too, you can't just give input to move if you're casting

#

so there must be some communication with those

dusty wigeon
#

Alright, so the abilities control the player ?

regal lava
#

abilities limit the actions of player I guess

dusty wigeon
#

The abilities says do X, do Y to the player ?

#

Then what is the issue ?

#

The player knows what abilities is being played

#

Abilities does not need to know anything about input

#

If the player "plays" the abilities

#

You might want to have the abilities control the player, that it is possible.

#

Then, at this moment, you have the first situation where you need to think a bit more.

#

Because now, you have a player that has abilities, and abilities that have the capacity to control the player

#

Is it our situation ?

regal lava
#

They do limit the player, yes. I think I can move some logic out of it though. It's something I been meaning to refactor for some time now.. hmm

dusty wigeon
#

If they limit the player, they do not control the player.

#

And we are still in an ideal situation.

#

As they do not need to know anything about the player

regal lava
#

Basically what you have there is what I am doing, so I guess the problem is more with my smaller scripts, or rather subscription systems.

dusty wigeon
#

Elaborate

#

What the subscription system does ?

#

What are the smaller scripts ?

brisk spruce
regal lava
#

Well, back to the modhandler. Abilities, equipment, player statistics rely on modification objects, which you can think of as gear affixes and even more sillier ones like trigger fireball when hit.

dusty wigeon
#

I'm listening

#

What are the events in this situation

brisk spruce
# regal lava Yeah, pretty much

Mood. Pretty much what I have brought up above was my solution. Im sure others exist but if you want I can hook you up with my guide I wrote on how to implement my approach if you like

regal lava
#

The events keep a lot of the stats and trigger effects updated, so when they are equipped, or learnt, they must contact each other and assure that they are updated accordingly with the newest mod.

brisk spruce
#

I also very quickly grew tired of all my monobehaviors becoming just a tangled mess of "everything referencing everything else" and a billion events all over the place, and it just felt like a spiderweb of things connected to other things

regal lava
dusty wigeon
#

Use a central system such as a modificator.

#

The modificator listen to what it needs to. The abilities add or remove a modification.

regal lava
#

Yeah, it could use some adjustments, but I think the idea is there for that I need to cache as much as possible because with what I have it's too much to calculate per hit

royal shore
#

~~```
ArgumentException: The number of vertices in the combined mesh (66792) exceeds the maximum supported vertex count (65535) of the UInt16 index format. Consider using the UInt32 IndexFormat for the combined mesh to increase the max vertex count.

this is what I get when I use the CombineMesh() am I doing something wrong?

```csharp

MeshFilter[] meshFilters = floor.GetComponentsInChildren<MeshFilter>();
CombineInstance[] combine = new CombineInstance[meshFilters.Length];

for (int i = 0; i < meshFilters.Length; i++)
{
    combine[i].mesh = meshFilters[i].sharedMesh;
    combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
    meshFilters[i].gameObject.SetActive(false);
}


Mesh mesh = new Mesh();
mesh.CombineMeshes(combine);
transform.GetComponent<MeshFilter>().sharedMesh = mesh;

Here's the code~~

regal lava
#

also a question i've been looking for, assuming I do cache all this stuff, how do I approach a problem that I remove some modification from an ability when it's on the scene. If I have it all cached, and I delete that reference, it'll create a bunch of errors.

dusty wigeon
#

The modifies part is what you struggle with I guess

regal lava
#

recalculating this off a rapid ability, from the player and allies, would add up quite a bit

dusty wigeon
#

So, you have performance issue ?

regal lava
#

yeah, it's actually quite a project with what elements ive been going with

dusty wigeon
#

Did you profile ?

regal lava
#

vampire survivors, diablo stats, rigid bodies, A*

#

vfx graph

dusty wigeon
#

Did you profiles.

regal lava
#

Yeah, without caching it creates quite a mess

brisk spruce
#

yeah thats pretty normal to do for a game like that

dusty wigeon
#

So, what you want is caching as you said.

brisk spruce
#

caching those stats and only modifying them when they have changed is pretty reasonable

dusty wigeon
#

It has nothing to do with events.

brisk spruce
dusty wigeon
#

It does needs to be tentacular.

brisk spruce
#

and as Mao said, there's a buncha different types of triggers that can cause the stats to require an update

regal lava
#

Yeah, it's quite a nest of operations and ability subsystems

#

if you have a spell that triggers a spell, then you need to now modify both lol

brisk spruce
#

@regal lava Ill just say this is an example of what my system excels at, since I even recently added a sort of mechanism to open a transaction and then commit it on my game state, so if I modify like 5 stats at once it wont retrigger the recalculation/redrawing 5 times, but once instead after I have finished making changes

dusty wigeon
#

You can do all of that in a subsystem like a modificator

regal lava
#

I cant actually find info how diablo-likes do it though, and when it comes to unequipping weapons with modifiers that affect abilities, I assume it snapshots the cache somehow to prevent you discarding that weapon and nulling refs

brisk spruce
#

I can do something like

using var txn = GameState.OpenTransaction();
GameState.Player.Stats.Strength = newStrength;
GameState.Player.Stats.Intelligence = newIntelligence;
GameState.Player.Stats.MoveSpeed = newMoveSpeed;
txn.Commit();

And it will then trigger all the distinct events that have been queued up, and wont re-trigger the same event twice, which is quite handy

dusty wigeon
#

Like how they do to keep the original stats ?

#

When you are doing an abilities ?

brisk spruce
regal lava
#

Even on another layer, when would I know to discard it then if the weapon is destroyed

dusty wigeon
brisk spruce
dusty wigeon
#

It is that simple.

#

Also, big project are usually a mess. They do what they with what they have and it is usually ugly as duck

#

The standard are most of the time low.

brisk spruce
#

Truer words have never been spoken XD

regal lava
#

Hmm, yeah let me think about the logic a bit more then. Perhaps I'm binding stuff too much, but right it shouldn't (but it does ^^ )throw errors regardless if I discard a weapon with a mod. Rather, it should just not apply the trigger anymore

brisk spruce
#

You try really hard to keep it not a mess, but somehow even with the best intentions and all the effort in the world, you still end up with at least some hacky spaghetti in there

#

But with a really good set of folks doing code reviews, you can at least keep your spaghetti index down to a reasonable level and under control

obsidian coyote
dusty wigeon
#

Also, there is no particular reason to optimize things if you do not have any issue in term of perofmrance.

brisk spruce
regal lava
#

rigidbodies on 500 enemies do be costly

#

may write my own physics eventually

dusty wigeon
#

You might want to use DOTS

#

If you are going for high enemies counts

regal lava
#

I would but too invested in this one now D:

brisk spruce
#

honestly usually I find the worst tech debt comes from when somehow something really hacky got snuck in a year ago and no one noticed and now like half the codebase is built on top of that, and fixing it would require refactoring almost the whole thing

dusty wigeon
#

Then you gonna deal with the limitation

brisk spruce
#

So you just keep piling more hacky workarounds and fixes on top of that and it just gets worse and worse cause your PM will never approve the 2 weeks of work to just fix the damn root problem, so instead everyone keeps piling the "workarounds" on top of the pile D:

dusty wigeon
#

Unity (GameObject) does not support well high numbers of enemies.

#

You have a long road of performance optimization and decision to do.

obsidian coyote
# dusty wigeon Same. hierarchy depth of 4-5 class of multiple thousdands lines

i recently rewrote a core system in the game to seperate it out from an existing nested spaghetti code class since the design team wanted to keep adding and changing shit with how it worked, and it was becoming super unmanagable to the point any time anything touched it, bugs would start cropping up. But now we gotta spend a bunch of time testing the rewrite since the original tied into a ton of systems all over :S

dusty wigeon
#

And yes, I know, it is costy to do so.

obsidian coyote
#

yeah, it seems like endless pushback the moment i sugest we rewrite anything lol

dusty wigeon
#

It is kinda hard to prove the $$$ values it gets.

obsidian coyote
#

but every so often the tipping point is finally reached where the amount of money going into keep something that is super broken going outweighs that of a rewrite lol

#

and yeah, project lead/company stakeholders are all about not putting dev time into anything if it isn't directly marketable to the end user ๐Ÿ˜ข

dusty wigeon
#

Even more when you have people that are king at what they do and they always find out a way to make something work fast.

#

I think the solution for that might to incorporate a minimal amount of time in "Maintenance" project each iteration.

brisk spruce
#

I find once I can convert it into tangible concrete numbers like, "Every week we waste about 5-6 man hours working around this problem, it would take about 35 man hours to fix it" suddenly approvals come a lot easier :x

obsidian coyote
#

the higher ups were all like "dont waste dev time writing tools since by the time the tool was written you could have already finished the task" i basically ignore that and write tools all the time, and they have saved me literally weeks of dev time at this point lol

dusty wigeon
#

I'm trying so hard to push for a build machine

brisk spruce
dusty wigeon
#

A fucking build machine

#

I'm like writing small bash file to automate building on the side.

brisk spruce
#

"this will cost us about 30 hours of work... but our devs will stop fucking quitting because the job wont be a hellish nightmare of onboarding so... you do the math on that one"

obsidian coyote
#

we have a build machine that every time a new merge is done into the build branch it spits out a build and a download link in the company chat so anyone can pull it down and use it for whatever

brisk spruce
#

At some point Im gonna make myself a build machine for my personal projects

dusty wigeon
#

It is like the most important things you need

#

I'm still fighting to have one and have time to setup it.

brisk spruce
#

Ideally what Id like is to decouple the build system from my git repo. I know normally the two go hand in hand but Id like to actually keep em distinct as systems

obsidian coyote
#

its nice cus marketing/etc dont use git and every so often they need a build do capture footage or qa needs one to test, etc.

dusty wigeon
#

Yeah, I'm gonna need to push more for that.

#

I'm looking at my colleague making a build for 30min each two days

#

Doing a lot of error in doing so

brisk spruce
brisk spruce
dusty wigeon
#

Yeah

brisk spruce
#

lets give er a whirl

dusty wigeon
#

Might want to clean up what you have also

#

Sometimes, you can close Unity and reopen.

#

Maybe deleting Library can help

brisk spruce
#

yeh that was it, thanks!

dusty wigeon
obsidian coyote
# brisk spruce yeh that was it, thanks!

so i was looking at that example you mentioned of the model view pattern, and started writing my own implementation, still pretty early stages at the moment, one thing i changed from your example was making my own version of these, since the original used classes which were allocating memory each time the events were called, not much mind you, but as a project gets bigger and some properties are changed on hot code paths, it can begin to add up.

brisk spruce
#

and then you can even drop the entire struct to just be a string right? I think you can make a delegate have an in value?

obsidian coyote
#

seems possible, ill have to do some more testing

brisk spruce
#
public delegate void PropertyChanged(in string propertyName);

Ill test this out

#

It looks like it works yup

obsidian coyote
#

does appear to work you just need to fully define it in the callback

brisk spruce
brisk spruce
#

@obsidian coyote this is the latest iteration of what I have, I havent added support yet for Enumerables but I plan to at some point
https://hatebin.com/nqrqpnayus

#

And then an example implementation would look like this:
https://hatebin.com/rohpgvblvq

And then you just subscribe to it via:

GameState.Bind(g => g.UI.SomeIntValue, OnSomeIntValue);

public void OnSomeIntValue(int val) { ... }
obsidian coyote
#

outa curiosity have you tried building your code with il2cpp compiler? i know some aspects of reflection, etc are unsupported by it, wondering if this all works within what's supported

brisk spruce
#

Itll prolly explode in its current state, I expect I will need to do a lot of fixing to make it work if I want it

obsidian coyote
#

ah fair enough

brisk spruce
#

@obsidian coyote aight for now I put all of the necessary code in one single gist here, which means if anyone finds fixes or optimizations or whatever they can even fork and open a pull request.

I think later if it gets big enough that a single file is just not enough, Ill break it out to a full blown github, but for now it feels small enough that 1 single .cs file is still valid (barely) for all the code to make sharing easy

https://gist.github.com/SteffenBlake/ace74a893d0b16c30a7eb2a42d6d9230

obsidian coyote
brisk spruce
#

If the subscriber cares about both of those fields, then I would have it subscribe to both fields.

If you want logic where like, setting Max Health automatically "caps" health if its greater than it, then I would add have that logic exist in the service layer that manipulates MaxHealth and Health

#

One nice thing is my logic supports subscribing to not just 1 specific member prop on a "leaf", you can subscribe to an entire "branch" of the tree.

As an example instead of needing to do:

GameState.BindTo(m => m.Player.Health.Current, OnHealth);
GameState.BindTo(m => m.Player.Health.Max, OnHealth);

You can just do

GameState.BindTo(m => m.Player.Health, OnHealth);

And if any value "beneath" Health changes, it will fire the event

austere jewel
#

I've not really been watching any of this convo and am just dropping in after randomly clicking on that script, but what is this for ๐Ÿ‘€
None of this will work in IL2CPP will it?

brisk spruce
obsidian coyote
#

ive tried some of the stuff and it works, havent tried pixxel's exact code tho, just my own version

austere jewel
#

LamdaExpression stuff, it's surely so reflection-based it won't build ahead of time

brisk spruce
#

Mostly its a question of whether this code works or doesnt work in IL2CPP:

public static string GetFullMemberName(this LambdaExpression memberSelector)
{
    var currentExpression = memberSelector.Body;
    if (currentExpression is not MemberExpression memberExpression)
    {
        throw new Exception("Member Expressions only!");
    }

    var name = memberExpression.Member.Name;

    while (memberExpression.Expression is MemberExpression next)
    {
        memberExpression = next;
        name = memberExpression.Member.Name + "." + name;
    }

    return name;
}
brisk spruce
obsidian coyote
#

my version doesn't use lambda expression stuff at all

brisk spruce
#

Like all its doing is just looking at the lamba object itself and "stringifying" it

dusty wigeon
#

I think System.Linq.Expressions works in IL2CPP

brisk spruce
#

I guess the other thing that might work or not is this:

public void BindTo<T>(Expression<Func<TSelf, T>> selector, Action<T> method)
{
    var fmn = selector.GetFullMemberName();
    var compiled = selector.Compile();
    var concrete = (TSelf)this;

    PropertyChanged += (in string prop) =>
    {
        if (prop != fmn)
        {
            return;
        }

        method(compiled(concrete));
    };
}
#

Particularily this line:

var compiled = selector.Compile();
dusty wigeon
#

Also, binding can be done with ILWeaving.

#

If you really intended to go hardcore, you might want to look into it.

brisk spruce
#

Im not sure what that is, but in my case the event is a string that represents the "path" to the property, and the expression just serves 3 purposes:

  1. "Hard Types" the method so we can automatically correctly bind in a typesafe way to the matching Action, note how I dont need to cast to a T in that logic
  2. I serialize it to a string which should match the same "path" value of the event. If it doesnt, something went horrifically wrong
  3. I compile it as a "getter" to actually get the value and pass it to the action
dusty wigeon
#

ILWeaving means to generate the codes (IL instruction), reducing even more the "boilerplate" and removing the limiation of IL2CPP.

brisk spruce
austere jewel
brisk spruce
#

I am not a fan of that sort of "post compilation" injection of code because now you cant debug that easily

dusty wigeon
dusty wigeon
brisk spruce
#

What I have there has pretty small amount of boilerplate per property, I feel like this isnt too bad:

private AbilitiesState abilities;
public AbilitiesState Abilities
{
    get => abilities;
    private set => BindChild(ref abilities, value);
}

private int roundCount;
public int RoundCount
{
    get => roundCount;
    set => Mutate(ref roundCount, value);
}

as an example, it's pretty light, and the upside is it is 100% debuggable and doesnt involve any particular magic stuff, it "just works" exactly as is

austere jewel
#

Well, whatever is landed on I'd want to be extra sure it compiles with Il2CPP if anyone aims to be using platforms that require it

brisk spruce
austere jewel
#

Building with it enabled

brisk spruce
#

I wouldnt be surprised if it doesnt work, but I also bet there may be workarounds to get it to play nice with it

obsidian coyote
dusty wigeon
#

IL2CPP can be a really pain to deal with.

austere jewel
obsidian coyote
#

ive had pretty good success with it, except with the webgl il2cpps stuff, seems to throw memory issues all the time :S

obsidian coyote
brisk spruce
#

I got a couple normal bugs from my latest set of changes, lemme hammer those out and then Ill see how badly IL2CPP breaks my stuff lol

dusty wigeon
obsidian coyote
#

as long as whatever is using the slow code is cachable, i think its ok

#

since its being done in a bind call, im assuming the result of the compile call is reasonably fast, even if the act of compile isn't

dusty wigeon
obsidian coyote
#

ooof

austere jewel
#

The slow code would presumably be the output from the generated expression, compile would be as slow as normal (as in, both are slow to compile)

brisk spruce
#

same for the .compile() calls

austere jewel
#

The output is interpreted though, that's the point

#

it's not like IL where the output is an actual compiled function, fast as it would normally be

brisk spruce
brisk spruce
wide anvil
#

Hi, does anyone here have experience making more intelligent enemy AIs using finite state machines and/or behavior trees? I am making a 2d top down game (think behavior like among us) and I was hoping that I could make AI that would accurately emulate a player. I have made basic patrolling and sentry AIs before with navmesh but I have never tried to make anything smart

#

Was just wondering where I should start with all this

obsidian coyote
#

i wrote an interpreter that i made to let people write scripts to control tanks and pit them against eachother, effectively my "compile" generates a closure containing nested closures that are setup as an abstract syntax tree, its performance isn't too bad, defiantly not native but considering its executing hundreds of nested functions i also wouldn't call it "slow", guessing the stuff produced by .compile() can't be much worse/better

austere jewel
#

As with anything I imagine it matters at what scale it's used

obsidian coyote
#

thats fair, if EVERYTHING uses the pattern in a larger scale game, it could become a bottleneck

dusty wigeon
wide anvil
#

yeah that's a pretty bad question lmao

dusty wigeon
wide anvil
#

Gotcha. I'm under a bit of a time crunch so I was just checking if it's something that I should even consider or not

dusty wigeon
#

Just collecting the various data to make something like that could take month

wide anvil
#

Makes sense

dusty wigeon
#

If your game is simple, I guess you might be able to use a probabilistic model though. Something like https://en.wikipedia.org/wiki/Expectationโ€“maximization_algorithm

In statistics, an expectationโ€“maximization (EM) algorithm is an iterative method to find (local) maximum likelihood or maximum a posteriori (MAP) estimates of parameters in statistical models, where the model depends on unobserved latent variables. The EM iteration alternates between performing an expectation (E) step, which creates a function f...

obsidian coyote
#

lol, these are very different things, you can easily make something that tries to kill an enemy when there is no one else around, but to try and "think" about how to do it in a way thats clever is a much more difficult problem

dusty wigeon
#

Either you try to imitate something or try to win.

hardy sentinel
#

but if you have that as a base you could amplify it quite a lot with ML and optimize paths based on other parameters
e.g.: positions of others, amount of players, previous votes per players, completed tasks, etc

obsidian coyote
#

imo ML might be worth investigating if the problem is not well defined, or there is no reasonably clear "solution", but i think for most peoples use cases that is overkill

brisk spruce
#

@austere jewel Oh so uh, turns out I have been on IL2CPP this whole time, I guess it works!

austere jewel
brisk spruce
austere jewel
#

IL2CPP only compiles C++ when you build, in the editor it's all just mono

hardy sentinel
obsidian coyote
#

my lil test game runs at 260-280 fps with a mono build, but around 480 fps with il2cpp ๐Ÿ”ฅ

hardy sentinel
#

doesn't even have to be super-intelligent, likely.. so yeah killing 2 birds in one stone xD

obsidian coyote
#

nah, its a user scriptable game, so if the user scripts are slow, i need to make sure the base game is as fast as possible to accomodate that lol

#

Anyone know why TMP_Text accepts a char array as input if it just turns it into a string internally anyway... I was trying to use a char array buffer that i dynamically replaced chars in to prevent string allocation, but it seems TMP just strings it anyway according to the deep profiler ๐Ÿ˜

sly grove
#

i've used that before and indeed saved the gc

obsidian coyote
#

hmm, maybe ill have to give it another go then

#

looked like it was causing allocations anyway when i tried last ๐Ÿคทโ€โ™‚๏ธ

sly grove
#

show your code perhaps

obsidian coyote
#

afaik that "Should" just keep updating the first char in the array to a random value between 0 and 9, then updating the tmp text via SetText(char[] arr)

#

might be something wrong in this contrived example since i just threw it togeather, but it appears to work ingame as you'd expect

brisk spruce
#

@austere jewel aight, looks like it fails, whats my best option for getting logs from an IL2CPP build to see whats failing when I publish it?

#

does unity handle logging out to a text file by default, or am I gonna need to setup some kinda hook to capture thrown exceptions at runtime somehow and log em out to a file

austere jewel
#

It logs to the editor log file, and the console

#

if it's published, then it logs to the player log

brisk spruce
#

Is there a good guide you know of so I have my settings correct and am running the IL2CPP version in the editor, such that I can replicate this occurance?

obsidian coyote
# sly grove show your code perhaps

Also appears to happen when using the specific "SetCharArray" call, but that shouldn't be surprising since it appearst to just call that internally if the input is a char array anyway ๐Ÿคทโ€โ™‚๏ธ

brisk spruce
#

To debug a Unity Player running on an Android device, connect to the device using USB or TCP. For example, to connect to an Android device in Visual Studio, select Debug > Attach Unity Debugger option. A list of devices running a Player instance appears.
Is this talking about the Unity Remote app? Or is this talking about something else entirely?

#

its annoying the docs just namedrop these terms and dont provide any further info about wtf a "Unity Player" exactly is

obsidian coyote
#

unity player afaik is just the actual built/running game on the device

obsidian coyote
#

ah guess they ghosted me.. oh well

brisk spruce
#

@austere jewel oh sick, I got it working now, debugger ftw

#

So turns out not only do you gotta do zenject's whole deal of enforcing [Inject] on all your class constructors that inject, but you even need to make sure you have empty constructors with that attribute even on injected classes that are "leaves", that dont inject anything

#

if you do that, it works, looks like at least my chunk of code is working totally fine for IL2CPP, it was just Zenject that was breaking cuz my couple "leaf" injected classes lacked that necessary empty constructor trick to make sure they got included in the build

#

but aside from that, all the stuff I shared in my gist appears to be totally kosher with respect to IL2CPP, Im not noticing any issues

austere heart
#

Can someone understand why there's major slowdown when I return to the first menu? The more I repeat this the longer it takes to get back.

hardy sentinel
#

oh u did.. sry was scrolled up ๐Ÿ˜„ yeah it stores as char array and gives you the option to get the string out of it

obsidian coyote
#

lol np, it seems like it shouldn't but for whatever reason it allocs a new string, seems like it sorta defeats the purpous of a char array input ๐Ÿ˜’

hardy sentinel
#

umm well myStr += "x"; allocates a new string as well, so

#

I guess they could've used a stringbuilder but is it really worth it?

obsidian coyote
#

would be REALLY nice if you could toggle some mode or w/e that prevents the string alloc so you can manupute the chara array directly and not worry about mem allocs for stuff like fps couters, or other stat based things

#

stringbuilder still creates a string

hardy sentinel
#

it only allocs the string once you request it, no?

hardy sentinel
#

I mean.. not each time you 'append' things to it

obsidian coyote
#

no not each time, but once you want to get the result of it, it does

#

for stuff like FPS counters, or health bars, or other stats that update frequently like weapon hit accuracy, or damage, etc. using a char array and just updating the chars in the array to the new value woulda been nice to be able to do, instead im stuck creating a pre-allocated lookup table for a large range of numbers to prevent the allocations

hardy sentinel
#

well I've created a input field using TMP as renderer

#

no reason you can't do it with TextMeshProUGUI as well ๐Ÿ˜„

#

(it's hard time for english but hope u got what I meant xD)

obsidian coyote
#

even storing just 2 digits of percision on a decimal number, 100,000 strings in a lookup table only gets you up to 999.99 numeric range :S

hardy sentinel
#

(yeaa.. even harder time for math.. I'll just take your word for it XD)

#

either way TMPro has nice internals for rendering, generating and utilizing fonts, etc

#

you should be easily be able to create an optimized FPS counter

obsidian coyote
#

yeah, it does, just sucks they don't give you the option to write to the char array directly without creating additional memory each time :S

hardy sentinel
#

probably an oversight from their end.. I don't see any reasons to alloc string when you set char array

#

but given the popularities of SetCharArray(..) and text_get() methods, I don't think it's unreasonable

#

also, it's probably optimized as an all-in-one package including input fields and stuff. I think they're quite a small team

obsidian coyote
#

apart from that, my game has no memory allocations once its running, unless the object pools need to alloc a new item, but then its saved for the next time its needed, so in my case its annoying lol

hardy sentinel
#

high-level UI code contains tons of todos, comments, and duplicate code.. wouldn't surprised if their not-best-engineers took on some of those tasks instead

obsidian coyote
#

drawing health bars just using the unity canvas and a slider works well enough, as for performance, if you pool them, they seem fine and don't appear to allocate any memory

hardy sentinel
#

well yeah the VertexHelper approach is if you REALLY care about performance -- like if you wanna render thousands

long ivy
# obsidian coyote the tmp code ๐Ÿ˜

are you sure this is called in builds? it looks like the only time it would be called in a build is when reading the text property back. The other calls are editor-only

obsidian coyote
#

hmm let me see

hardy sentinel
#

but for millions some compute shader for calcs, along with fragment shader for rendering at the appropriate position would work best

obsidian coyote
austere heart
#

Can someone understand why there s major

obsidian coyote
#

cool, does look like the char[] option on tmp doesn't actually alloc the string when its a build ๐Ÿฅณ

pulsar fable
#

Quick Question: Unity player setting has a option in Resolution and presentation by name "Render over native UI". I need this setting to be turned for a specific need; but as sson as i turn it on; any image /font or any game component that has alpha lesser tha 255; will start displaying actual screen of the operating system;

obsidian coyote
#

guessing the render over native ui literally means use the system desktop as the clear buffer, so it soulds like its working as intended, why do u need it?

near escarp
#

does anyone know how to instantiate the default builtin unity textmeshpro inputfield through code? this is without creating a prefab manually and saving it to my assets. my first approach was to simply add the TMP_InputField component to an empty gameobject but as you might assume it didn't work. only the component itself was added while everything else is missing. font assets, background sprites, etc, etc. I found the following code online from a forum post GameObject go = TMP_DefaultControls.CreateInputField(GetStandardResources()); which is supposedly from the unity source code? but idk how to get the standard resources that's supposed to go in the createinputfield method

near escarp
#

oh so the method is private. interesting. so I can just get it through reflection

obsidian coyote
near escarp
near escarp
obsidian coyote
#

the immediate mode gui is not just layout, it allows you to drive the whole ui if u want, its the original way unity ingame ui's were done before the whole canvas style ui

near escarp
near escarp
flint sage
#

Well those methods are unavailable

#

So you can't really

near escarp
#

what methods? assetdatabase?

flint sage
#

Yes

near escarp
#

hmm

obsidian coyote
flint sage
#

It's not Dear IMGUI

#

It's a custom system

near escarp
#

I know there's Resources.GetBuiltinResource but idk if that can be used to access any of the required assets. probably not

long ivy
#

you don't need the methods, just the resources. Copy pasta that code, set sprite references, generate the struct it needs at runtime

near escarp
#

yes but the question is whether or not I can access the resources at runtime

flint sage
long ivy
near escarp
#

as expected I can't load the sprites from the given paths using Resources.GetBuiltinResource. idk if there's a way to list al the built in resources (not from the assetdatabase of course). but it seems to be able to instantiate the inputfield without sprites. but I'd still like to get it working if possible

near escarp
long ivy
#

you grab the references to sprites and store them in a SO. Then at runtime or a build, you create the struct that TMP_DefaultControls.CreateInputField needs

near escarp
long ivy
#
  1. Create the SO asset
  2. Go to Tools/Get TMP Resources to auto-populate those fields
near escarp
#

I just did

long ivy
#

that looks like you're looking at the script

near escarp
#

I can press it again if you want

#

nothing happens?

long ivy
#

did you create an instance of the SO?

#

your screenshot is not looking at the right thing

near escarp
#

but can I even get an use the asset's references at runtime? I mean when it builts those default assets are not included in the build?

#

so even if I have the references they won't point to anything

long ivy
#

everything you reference is included in the build

near escarp
long ivy
#

Create > TMP Resources SO

near escarp
#

I'm not building from this. it's for modding. the game I'm modding is already built. I won't be the one controlling the build

long ivy
#

that seems like an important detail you forgot to mention

#

nothing you reference will be included unless your mod loads the references itself, so it'll still work fine if you're making an AssetBundle

near escarp
#

I thought I had already mentioned but I think I mentioned it in unity-talk when I was first trying to get help there. moved to this channel because the other one wasn't helpful

#

so at the end of the day I need to create an assetbundle with the resources I require?

long ivy
#

or find them at runtime in some way, and I can tell you from experience that would be very tedious if you want to do anything of significance. Sometimes it's easier just to hijack some existing element yourself and repurpose it if you're not building something huge

near escarp
#

yea maybe I can use the background sprites and such from existing input fields. would also make sense to keep the same style

#

only problem is the input field I created using CreateInputField doesn't seem to have a caret and idk why. I did try to copy the caret from an existing input field but that didn't work

real blaze
#

hey; so, I just realized a Trigger in animator is left checked until it's used. so, if you set a trigger named Jump, this Will not be unchecked until it's consumed by a state node

#

so, any idea how best to achieve a real trigger thing? something that gets checked for just one frame

hushed fable
#

Bool that you toggle off in the next frame

scenic forge
#

nah its a user scriptable game so if the

hazy geyser
#

is it possible to build a file downloader that downloads files simultaneous using the parallel job system?
or will i likely run into some problems using this method.

jaunty leaf
#

Quick question
Is it possible to use unitys ECS outside of unity?
Like within a .net console app?

I'm currently using a 3rd party one but would love to use unitys. I don't care about burst or jobs, just the ECS code

flint sage
#

No

jaunty leaf
long ivy
sly grove
#

But yeah naturally the ToString creates a string

sleek terrace
#

How to increase mesh rendering speed/fps?
I am doing procedural generation mesh
I have rendered the hexes individuals and combined them to make a tile map like system

sly grove
#

the answer is - static batching or the SRP batcher, depending on your render pipeline

sleek terrace
#

ok thanks

harsh canyon
#

@plucky laurel hey, how are you, I have designed my FSM just like you suggested and its much better, but I have one problem, I dont know where to store some of my variables

#

some variables need to be shared between transitions and states

#

i guess one solution is to put those into a seperate class but i dont think thats very elegant

dusty wigeon
#

And which state needs to have share data.

harsh canyon
#

i have an fsm for enemy ai

#

i had a problem where a state and a transition needed to communicate

#

i mean share a variable

#

i actually could fix it by having the transition handle the logic, but i just got lucky with the solution this time

#

i dont know what i would actually need to do if one of my states needs to share a variable with a transition

#

both state and transitions are abstracted

dusty wigeon
#

The transition should be able to read the state ?

#

A transition would be specific on a given state.

#

TransitionFromAToBInCondition

#

Transition would know about a and b.

harsh canyon
#

yeah it is able to read the current state

dusty wigeon
#

So, what is the issue ?

harsh canyon
#

but let me try to explain

#

let me think how to say this

harsh canyon
#

so reading the state wont help

dusty wigeon
#

Where is the variable then

harsh canyon
#

so I have an FSM and I have an Enemy2 that derives from the fsm

#

the variable is in enemy2

dusty wigeon
#

an FSM should be a component of an enemy

#

enemy shouldnt derived from it.

#

Not every enemies need an FSM

harsh canyon
#
public class Enemy2 : FSM, IDamageable
dusty wigeon
#

Let's stay on the subject, what about the variable

harsh canyon
#

so if the variable is in enemy2

#

i cant pass enemy2 to the transition, as that wouldnt make the transition re-usuable

#

for example if i have enemy3

dusty wigeon
#

In that case, interface would be the solution

harsh canyon
#

i will get an error

dusty wigeon
#

Also, you wouldnt have this issue if you had made 1 enemy class.

#

Which is how you probably should do things

harsh canyon
#

for different behaviours

dusty wigeon
#

public class Enemy2 : FSM, IDamageable, IEnemyThatCanBeUsedInStateBecauseIDecidedToMakeMultipleClassOfEnemiesThatDoNotDeriveFromASingleClass

harsh canyon
#

oh instead of FSM you think it should derive from enemy?

dusty wigeon
#

Prefarably you would do:

public class Enemy2 : Enemy, IDamageable
harsh canyon
#

like abstract it once more?

#

i see yeah

dusty wigeon
#

Then, your state can work with enemy

harsh canyon
#

i had this idea yes

dusty wigeon
#

You can also do a cast if necessary.

#

if(enemy is Enemy2) then...

#

It is not something is recommanded

harsh canyon
#

yeah no thats ugly

dusty wigeon
#

Bad pattern. But it is possible

harsh canyon
#

thanks for helping out

regal olive
#

I'm looking to have my player be able to visually pick up objects. How would I map their hands to the object?

dusty wigeon
regal olive
#

thanks ๐Ÿ‘

wintry idol
#

Hey, anyone know a better way or know why i have the problem ?
When my Character was created, i use playfab as a CharacterData DB.
Code should be clean but when i have more than 10 keys and Values in my Dictionary, i got a console error message from playfab with "InvalidParams".

public void CreateDataStructureForPlayFabCharacterBlock1()
    {
        var request = new UpdateCharacterDataRequest();
        request.CharacterId = characterID;
        request.Data = new Dictionary<string, string>()
        {
            {"Forename", characterData.foreName},
            {"Lastname", characterData.lastName},
            { "Age", characterData.currentAge.ToString() },
            { "Current Position X", characterData.currentPosX.ToString() },
            { "Current Position Y", characterData.currentPosY.ToString() },
            { "Current Position Z", characterData.currentPosZ.ToString() },
            { "Currency Gold", characterData.currentCurrency1.ToString() },
            { "Currency Silver", characterData.currentCurrency2.ToString() },
            { "Currency Copper", characterData.currentCurrency3.ToString() },
            { "Minimal Level", characterData.minLevel.ToString() }
            
        };
        
        PlayFabClientAPI.UpdateCharacterData(request, OnUpdateCharacterDataSucceed, OnUpdateCharacterDataFailed);
    }

Thats the code, how it works... with more Values ---> ERROR

dusty wigeon
sly grove
#

for example

{
    "code": 400,
    "status": "BadRequest",
    "error": "InvalidParams",
    "errorCode": 1000,
    "errorMessage": "Both username and email are required unless specified with RequireBothUsernameAndEmail."
}```
#

the error message should have more details

wintry idol
dusty wigeon
#

And as stated by PraetorBlue, the error should contains more information.

wintry idol
wintry idol
# sly grove Playfab will return more info than just "Invalid Params"
UnityEngine.Debug:Log (object)
PlayFabManager:OnUpdateCharacterDataFailed (PlayFab.PlayFabError) (at Assets/PlayFabManager.cs:489)
PlayFab.Internal.PlayFabUnityHttp:OnResponse (string,PlayFab.Internal.CallRequestContainer) (at Assets/PlayFabSDK/Shared/Internal/PlayFabHttp/PlayFabUnityHttp.cs:220)
PlayFab.Internal.PlayFabUnityHttp/<Post>d__12:MoveNext () (at Assets/PlayFabSDK/Shared/Internal/PlayFabHttp/PlayFabUnityHttp.cs:159)
UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)```
dusty wigeon
wintry idol
#

But this is, that what i get. o.O

dusty wigeon
#

Read the documentation if you can't figure out how to access an error code.

sly grove
#

in other words you get to pick which function runs when it fails

#

and in that function you can definitely access all these things

wintry idol
wintry idol
sly grove
#

you can also print errorMessage

#

or errorCode

#

etc

wintry idol
#

aaaahhh

#
/Client/UpdateCharacterData: Invalid input parameters
Data: Too many keys specified in Data dictionary update. Limit is 10 and request contained 57.
UnityEngine.Debug:Log (object)
PlayFabManager:OnUpdateCharacterDataFailed (PlayFab.PlayFabError) (at Assets/PlayFabManager.cs:489)
PlayFab.Internal.PlayFabUnityHttp:OnResponse (string,PlayFab.Internal.CallRequestContainer) (at Assets/PlayFabSDK/Shared/Internal/PlayFabHttp/PlayFabUnityHttp.cs:220)
PlayFab.Internal.PlayFabUnityHttp/<Post>d__12:MoveNext () (at Assets/PlayFabSDK/Shared/Internal/PlayFabHttp/PlayFabUnityHttp.cs:159)
UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)
sly grove
#

well there you go!

#

at least you know for sure now it's an explicit limit of 10

vale zenith
#

Anyone know why AudioSettings.dspTime would run faster than Time.timeAsDouble?

DSP Buffer Size is 1024 and my FPS is 90, so Update() is happening ~twice as fast as audio buffer updates.
But the same exact results occurred even with Buffer Size set to 256.

`Start(){
int delayUntilCheckpoint = 1;
double dspCheckpoint = Audiosettings.dspTime + 1;
double timeCheckpoint = Time.timeAsDouble + 1;
double checkProgressTime = timeCheckpoint - .05; }

Update() {
if(Time.timeAsDouble >= checkProgressTime){
Debug.Log(timeCheckpoint - Time.timeAsDouble);
// Returns ~.04 as expected
Debug.Log(dspCheckpoint - AudioSettings.dspTime);
// Returns ~ -.08 consistent negative value. Expected result is a positive number }}`

If I make the checkProgressTime .2s before the checkPoint (instead of .05 in example), the DSP comparison will (barely) be a positive number.

So why would the Audiosettings.dspTime be so far ahead of Time.timeAsDouble..? I would have assumed it's because it updates the buffer every .2s (1024 dsp buffer size)
so it "jumps ahead" instead of incrementing linearly like Time.timeAsDouble, but the issue happened even with smaller buffer sizes, so..

thorn flintBOT
#
Posting code

๐Ÿ“ƒ Large Code Blocks
Large code blocks should be posted as links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/
https://paste.myst.rs/, https://hastebin.com/

๐Ÿ“ƒ Inline Code
Surround code with three backquotes. Not quotation marks.
To get C# formatting the first line should only contain cs or csharp.
Add a comment with a line number if there is an error message.
```cs
// Your code here
```
Do not share screenshots of code unless requested.

sly grove
#

it also won't respect Time.timeScale

dusty wigeon
#

Also, you gotta use OnAudioFilterRead if I am correct.

#

It does not update at the same moment of the standard Update

supple gulch
#

any way to set a custom transform matrix for an object? not seeing a clear way in the api

#

I'm trying to skew the vertices of a standard MeshRenderer dynamically

vale zenith
tall ferry
supple gulch
#

Is it not possible to apply this on the unity side, through changing the localToWorldMatrix? that would allow the use of any underlying shader

#

(also recalculating the mesh data would be waaaaaaaaaay too slow)

dusty wigeon
tall ferry
supple gulch
#

y'all I really don't need to use either of those, I'm just trying to get around the fact that Renderers don't let you easily skew vertices, even though they totally could

dusty wigeon
#

Also, renderer has nothing to do with the mesh.

tall ferry
#

we just provided u the different ways of skewing a mesh, how do you not need either of those when your problem is skewing a mesh

supple gulch
#

you can change the localToWorldMatrix to do the same thing with much less effort and processing

#

It's just a readonly field on Renderer

#

which is the problem

dusty wigeon
#

What are you talking about ?

#

Are you asking how to move a renderer ?

tall ferry
supple gulch
#

that would affect every object, so not quite

tall ferry
#

you can have separate cameras

supple gulch
dusty wigeon
#

You can do the same in a shader

#

You can use whatever matrix you want.

#

Do whatever you want with the position of the vertices

supple gulch
#

I'm not asking for alternatives rn, is there a way to set it in unity?

I know how to use shaders to accomplish the same effect, which I will do if there are no alternatives

dusty wigeon
#

This why graphics card have been invented

#

To process the position of the vertices and other things

supple gulch
#

I don't think you understand me

I would like to modify the existing localToWorldMatrix that is then passed to the shader, so the existing shader code can work with no modification

dusty wigeon
#

What is so hard with that ?

#

transform.positon = MyPosition;

supple gulch
#

you can't skew a mesh like that

dusty wigeon
#

By your terms.

#

Because localToWorlMatrix is that.

supple gulch
#

it could if you could set a custom one

dusty wigeon
#

Yes, the positon of the renderer.

#

If you want something else, you create a variable in shader

#

Then you populate it.

#

This is how it is done.

supple gulch
#

it doesn't have to be a rigid transform (only translation, scale, rotation), , it can be any 4x4 matrix

dusty wigeon
#

Anyway, what you want is a shader.

supple gulch
#

maybe there's something I'm not understanding

is there some secret rule that the transformation from model space to world space has to be rigid and otherwise stuff would be bad?

#

I guess I could just make a small rewrite of MeshRenderer

dusty wigeon
supple gulch
#

but then I probably couldn't use SRP batcher

#

hmm I could also overrride the default MaterialPropertyBlock, that would work too (and also not affect other game engine code I think)

dusty wigeon
#

But are ready to skew with other things that are not made for that.

supple gulch
#

because I would like this to apply to any object, regardless of the underlying shader (which should work)

#

otherwise a shader variant is necessary for every kind of object that has this effect applied

#

I'm not using an uber shader

dusty wigeon
stuck plinth
uneven mauve
#

This is more of a general programming question for algorithms but I'm implementing it in Unity so language specific terms are needed. I'm designing a system to allow a user to build a structure in 2D space. They can place pipes with bends, joins and straight pieces. Each piece is "square" and fits in a 1x1 area so coordinates (1,4) can contain 1 pipe of those variations. I was considering storing using classes for each coordinate that has something placed then store all the pipes in an array (an array of created classes). Firstly, is that the best way for speed? Given they are pipes, how could I calculate the internal volume of them using this system? For example, I need a function to say "Is (3,6) connected to (4,1)"

stuck plinth
#

depending on how much different behaviour there is between different pieces you could consider just storing enum values in your grid, and if you do want your parts to have their own classes then you probably only need one instance per type and all the coordinates using the same piece can reference the same instance?

uneven mauve
#

Yeah, I've been working on that before actually programming as it could be really bad to do some of the stuff I need at high frequencies

uneven mauve
dusty wigeon
#

Do you need performance ?

uneven mauve
#

Yes

#

Heavily

dusty wigeon
#

Then, using class is a bad idea.

#

You want sequential data storing.

uneven mauve
#
{
  "type": "straight",
  "health": 100,
  "x": 0,
  "y": 0,
  "neighbors": [
    {"x": 1, "y": 0},
    {"x": 0, "y": 1}
  ]
}

I was going to store it like this (With some changes) to keep track of neighbours

uneven mauve
#

That sounds complicated ๐Ÿ˜‚

dusty wigeon
#

You better off with a grid.

#

(If it is not too sparse)

#

Also, why you need to specify neighbors ?

#

You can simply define the actual pipe cant you ?

#

And, you would better be off using a bitmask

uneven mauve
#

For the pipes to contain "pressure" so some way of checking if one pipe has a "leak" then decrease connected pipe pressure. But there would be shut off valves at places to stop total leaks

#

The user could go 1000 pipes in one direction but 10 in the other so would the grid be fixed size?

dusty wigeon
#
[Flags]
public enum Neighbors {
  North = 1 << 1,
  West = 1 << 2,
  South = 1 << 3,
  East = 1 << 4
}
uneven mauve
#

Wow

#

That is wow

dusty wigeon
dusty wigeon
uneven mauve
#

Alright I have a rough idea on bitmasking thiny. To just clear up how the pipes work, they are of fixed shape such as straight, bent, T or 4way and don't adjust based on neighbours

dusty wigeon
#

If you have like 10000x10000 then you have a couple of 100 MB.

dusty wigeon
#

You can even have 2 fields

#

One for the type and one for the rotation

uneven mauve
#

Hmm I see, would that be easy to calculate "is connected"?

stuck plinth
uneven mauve
#

Ah that could be another bit

#

Yeah chunks for only constructing a specific amount on screen at once

#

Not all the pipes else it could lag

dusty wigeon
uneven mauve
#

Having all of the pipes in the scene at once could be an issue, especially if they need to make calculations like pressure

dusty wigeon
uneven mauve
#

Right

dusty wigeon
#

In mathematics and computer science, connectivity is one of the basic concepts of graph theory: it asks for the minimum number of elements (nodes or edges) that need to be removed to separate the remaining nodes into two or more isolated subgraphs. It is closely related to the theory of network flow problems. The connectivity of a graph is an im...

#

There is a ton of resources.

#

It is really a well documented subject.

uneven mauve
#

I see, so I can't just check if it's connected upon creation and store that value for both the created and each neighbour?

uneven mauve
#

So basically, the player can "place" pipes in a grid cell

stuck plinth
#

for pipes on a grid, you can probably go a long way with a boring old flood fill

uneven mauve
#

Yeah, pressure is important and idk if Unity can just simulate it

dusty wigeon
#

This is also a type of connectivity algorithm.

uneven mauve
#

ah.

dusty wigeon
#

You gotta do it.

#

Unity is not a physic engine

#

It is a game engine.

uneven mauve
#

So for overall architecture still, no classes? Start small with something like 10x10 area and store every tile?

#

Even if it's empty?

dusty wigeon
#

For performance, yes.

#

Keeping in mind memory allocation.

#

You might need other method.

uneven mauve
#

Hmm

dusty wigeon
#

However, an array is the best in term of performance.

uneven mauve
#

10x10 chunks still feels important

dusty wigeon
#

10x10 is nothing

uneven mauve
#

A 2D array?

dusty wigeon
#

Yes, a 2D array.

uneven mauve
#

Right

#

Just to throw in an extra complication, 0,0 is the center, and it has - coordinates preferably

dusty wigeon
#

I would consider chunk to be 1000x1000 in size.

uneven mauve
#

Ah

#

That's rather large lol

dusty wigeon
#

I mean, it depends what you are doing.

#

But 1000x1000 fits pretty well in memory

dusty wigeon
#

Also, if 1000x1000 is pretty much your whole grid, then I would not even consider using chunks.

uneven mauve
#

A very large build limit would be fine

#

Easy to switch out a few numbers if needed

tiny pewter
#

I will consider using dictionary unless player can place lots of pipe, 1000x1000 maybe wasting lots of memory though accessing is faster than dictionary or even a quad tree

uneven mauve
#

Yes 1000x1000 would be very large. They would really not need that much to start, but it could be a lot of growth late game

dusty wigeon
uneven mauve
#

Very sparse

#

Potentially tons of empty space

stuck plinth
#

a dictionary is definitely the easiest way to start something like this, your grid is infinite that way, but depending on how your game logic needs to access it, you might run into performance problems sooner

dusty wigeon
#

Then, you might want to sacrifice some performance for memory.

uneven mauve
#

20-50% filled where they are

dusty wigeon
#

Not that sparse

uneven mauve
#

Well it wouldn't be 50% of the entire grid, just where they build

#

So for example, they make a small set of pipes in the middle starting area

dusty wigeon
#

20% is not sparse.

uneven mauve
#

It wouldn't be 100% full

#

that small central area that is "busy" would be like 50% full

regal olive
#

How do you code out a slope system like in character controller for rigidbody

dusty wigeon
#

You could always have a chunk for growing up.

dusty wigeon
regal olive
uneven mauve
uneven mauve
#

Then they can build out further later?

uneven mauve
regal olive
dusty wigeon
stuck plinth
regal olive
uneven mauve
#

Like that?

dusty wigeon
regal olive
#

I asked how to code out a slope management system just like that one in character controller FOR rigidbody

#

like i want character controller level code

dusty wigeon
regal olive
#

you gave me a google search link

#

;-;

dusty wigeon
stuck plinth
tiny pewter
#

You donโ€™t have to store the coordinate of neighbours ,they can calculated in run time simforces have shown you you can use one-char number to represent neighbours

dusty wigeon
#

It is literraly open source.

uneven mauve
#

but as an example

tiny pewter
#

From my experience the vertex should store it coordinate in graph

uneven mauve
stuck plinth
#

it's going to be slower because if you need to go through the neighbors, each one needs to be looked up in the dictionary, but you can work around that

#

for example you could store your tile instances separately in a list too and instead of storing the coordinates for neighbors you could store their indices (if you don't mind doing some extra work every time you recalculate the neighbors)

uneven mauve
#

Indicies as position in the list?

stuck plinth
#

yeah

uneven mauve
#

What if something is added to the list? like a new pipe

#

It just goes at the end?

#

And this isn't risky to go wrong?

tiny pewter
#

You just use bitmask to check if neighbour in one direction exists then calculate it coordinates ,you can calculate how much memory one vertex needed

uneven mauve
#

Right calculate direction of neighbour. I might as well go back to the enum and not worry about what "type" the neighbour is and just say "connected to a pipe in the north" like earlier was discussed

#
[Flags]
public enum Neighbors {
  North = 1 << 1,
  West = 1 << 2,
  South = 1 << 3,
  East = 1 << 4
}
stuck plinth
#

how you store the neighbors is kind of up to you, but if you need to fetch the actual tile by its coordinates a lot, that's slower to do with a dictionary than if it was in a grid where finding something by its coordinates is super fast

#

depends on your game though!

dusty wigeon
#

It is still arguably fast though.

uneven mauve
#

Surely a dictionary with the indicies as the key is fast?

dusty wigeon
#

Cache miss, hashing, collision

uneven mauve
#

So a grid will be faster, even with TONS of empty space?

dusty wigeon
#

It is just a question of memory.

uneven mauve
#

To start, 99.99% will be empty. End game, 99% will be empty

#

on 1000x1000

cursive patrol
#

hashmap indexing is the same speed as array indexing because a hash map is an array under the covers

tiny pewter
#

Btw The neighbour should be 1<<0 to 1<<3
One to one mapping vs many to one mapping

dusty wigeon
#

Which can be solve with other method

uneven mauve
#

That's not my enum code lol. Never used it before

tiny pewter
#

If all the bits are zero then no neighbours

dusty wigeon
#

Oh, yeah my bad 1 << 0 = 1.

uneven mauve
#

I still haven't got a final conclusion of grid or dictionary. I feel dictionary would work better as 99% of space will be empty even for the most extreme player

dusty wigeon
#

Might better to just use:

[Flags]
public enum Neighbors {
  None = 0,
  North = 1,
  West = 2,
  South = 4,
  East = 8
}
uneven mauve
#

1,000,000 tiles and they will barely will 1,000

dusty wigeon
#

You can also have multiple grids

uneven mauve
#

Like the chunks yeah

stuck plinth
uneven mauve
#

That would create other issues such as calculating pressure across chunks

#

Alright thank you!

#

Dictionary final answer

#

Then neighbours with enum

stuck plinth
#

but it's impossible to say where your performance problems will start until you make the rest of the game ๐Ÿ˜„

uneven mauve
#

key is the coordinates

#

Just JSON right? No class to produce the object?

stuck plinth
#

well you'll need some objects as your dictionary values i assume, not sure how the json fits into it!

uneven mauve
#

Ah right c#

#

I uhh

#

Javascript

#

Anyways Back to the C# world

#

idk where to even start lol

#

Potentially make a new script for storing the data in some type of manager

brisk spruce
#

A single straight pipe that is 1 unit long or 1000 units long shouldn't use any different memory, it's just a vector + origin

uneven mauve
#

Because they are "components" with T parts and 4way connectors, each built seperately

brisk spruce
#

Jumctions can be stored seperate from the pipes themselves.. but is there a reason you even need to support them building a T junction that has 1 part unconnected?

#

Why not make an elbow turn into a T automatically when a third pipe is connected

uneven mauve
#

For this game, it wouldn't be suitable

brisk spruce
#

How so?

uneven mauve
#

There aren't long straights, lots of bends and the pipes don't necessarily touch because they are neighbours

brisk spruce
#

That's fine, what I said still applies

#

An origin+vector is still way less data almost always

uneven mauve
#

I am very confused on how this would work

brisk spruce
#

There's theoretically a "worst case" scenario that maybe makes storing every cell individually be as bad

#

If you have this, you dont need to store "Theres an intersection in the middle", thats already something you can implicitly discern from the fact the vectors intersect

#

No matter how long/short those lines are, that still just takes 4x Vector2s. Each line is just 2x Vector2s (1x Origin + 1x Offset)

uneven mauve
#

Yeah I get that

brisk spruce
#

You can effectively just treat each one as

struct Pipe {
    Vector2 From;
    Vector2 To;
}
uneven mauve
#

Right but what if it turns at every cell in a diagonal step pattern?

brisk spruce
#

Thats the worst case scenario effectively

uneven mauve
#

What about forks?

brisk spruce
#

nah those are fine

#

this is still just 2 "lines"

uneven mauve
#

What about a loop of pipes?

brisk spruce
#

What about it? A square is 4 lines

uneven mauve
#

You just define each turn?

brisk spruce
#

basically yeah

uneven mauve
#

As in a very long complicated loop

brisk spruce
#

The topographical result is not really relevant to how you store/process the data

tiny pewter
#

Actually this may running into trouble when running dfs, you cannot effectively distinguish the neighbour of vector

tiny pewter
#

And modify neighbour as well

brisk spruce
#

We were talking about pressure and stuff right?

#

Most games dont treat each individual "unit" of the pipe as a seperate entity, but instead would typically handle each "length" of the pipe as a single thing

uneven mauve
#

Kinda my thoughts

#

Although it's pipes, they aren't really long pipes, just small squares that connect

brisk spruce
#

Yeah that should just be handled as how you render them, but for actual logic I would take a more complex topography like this and treat it as such, where each colored "strip" of pipe is a single "thing" and you just track which pipe "segment" connects to which other pipe segment(s) via a Dictionary<Segment, HashSet<Segment>>

#

the lengths of those segments can be arbitrary, like the bottom right square could be huge and top left one small

#

But Id just treat each Corner -> Corner "strip" of pipe as 1 single "thing"

uneven mauve
#

And I thought I was lost before we added the colours ๐Ÿคฆ

#

It still feels like it may be better with the dict

brisk spruce
#

Now if there's like any kind of interactable or like, special placeable thingy that can interrupt or change a pipe, Id also consider that a "break" in the segment, like so:

#

I dunno if you have stuff like that but I think I read something like that

brisk spruce
tiny pewter
#

But how can you get the segment player interact with in O(1) time

brisk spruce
uneven mauve
#

I really appreciate the idea, but I think it's a little complicated to start

tiny pewter
#

Though I believe it can get within O(log n)
Given a coordinate and a set of edges represented by pair of vector2int determine the edge coordinate located at(it may be none)

brisk spruce
#

The only hard part is actually handling "splitting" a segment

#

Thats what I forsee as the largest challenge, if you get that part worked out its home stretch after that

uneven mauve
#

Right so I have the actual data structure, but how should I actually make this code? A new blank file specifically for structure management? I already have the script for placing the pipes

#

What do I attach it to? The same as the empty controlling all the built parts?

brisk spruce
#

99% of my logic isnt "attached" to stuff and just sits inside of my game engine's stack of POCO services

tiny pewter
#

Splitting the segment by give two points is actually finding two points at same or different segments

uneven mauve
#

So just a blank C# file, do I not need start and update? I'm very new to actual unity programming.