#archived-code-advanced

1 messages · Page 176 of 1

sly grove
#

One of my weapons is not beeing rendered if it's not visible in the scene view in the editor???? so it's clearly not about the scene view

midnight violet
#

Well, I guess your weapon is being culled at some point.

undone coral
#

don't use scenes. make your level content a prefab

midnight violet
#

Or your mesh normals are inverted or or or. take another mesh and test, use a primitive for testing purposes

unique ermine
#

Very weird indeed.
I'll test it some more

midnight violet
#

You can also try to put your not visible weapon right in front of your camera, so your main cam does see the whole mesh and not just parts

undone coral
#

what kind of game are ou making?

undone coral
#

@serene girder you had a bug where you got into a lot of red herrings

unique ermine
#

1sec

serene girder
#

i also fixed the issue by making a separate variable

undone coral
#

have you looked at a tower defense asset?

#

to study how things work?

#

you could learn a lot

#

depends what your goals are

sacred orchid
serene girder
#

@undone coral not really, i like documenting myself on the go, and so far I haven't gotten problems, jsut these strange interactions that are more algorithm wise

granite viper
serene girder
#

I know it doesn't

undone coral
#

@serene girder it's okay. focus on this journey as a programming learning exercise 🙂

serene girder
#

thanks, im making it for my bachelor project

undone coral
# unique ermine 1sec

there are traditions to writing FPSes and solving these problems. what is the goal?

robust citrus
#

is there a way to force your project's [FormerlySerializedAs] attrs to propagate their new names to their scene/prefab/scriptableobject fields? i hate leaving these attrs around forever

sage radish
plain abyss
robust citrus
sage radish
robust citrus
#

thanks!

normal cedar
#

I was thinking of generation a huge portion of the map beforehand and then splitting it up but not only is that really expensive. if you generate more than that it would still give the same issue

unique ermine
midnight violet
frank ferry
#

Guys quick question, if I have made all my projects in unity version 2020.3.29f1 and then upgrade to 2020.3.31f1 would I get the prompt that I would need to convert all my projects to that version? or since its the same year will it not need to?
Because the computers at my college have unity 2019.2.8f1 installed and I am wondering if I install 2019.4.36f1 would I need to keep converting to and from versions?

sly grove
sly grove
#

you are free to continue using the older version of the editor with your project indefinitely

frank ferry
#

do I need the exact same version on both computers so that I wont need to keep converting to and from

sly grove
#

yes

frank ferry
#

alright ty

umbral trail
#

you could ask that a LTS version is installed

azure jewel
#

im not sure if this is the right place but i wanted to have a formula field on the inspector for something like "3 * atk + 2 * def" but im thinking it might be bad for performance to evaluate the expression every time the action is executed is there a way to compile the formula string into C# code programatically as i press play (or maybe its better during compile), how can i do it? or is it possible?

for context, i have a scriptable object for AbilityAction so that an Ability can just execute a list of actions and i wanted to make a Deal Damage AbilityAction that I could put formulas instead of constant floats

sly grove
#

yes it's possible, no it's not trivial to do it right

undone coral
#

can Debug.Log be set to output dates and times in the Player.log?

#

is there a global setting for the logging format?

#

too much noise on google

azure jewel
frank ferry
fresh salmon
#

There is, but it involves string manipulation, ie. a parser whose complexity depends on the structure of the string

#

It can go from a simple string split and a few int.Parse calls, to a char-by-char analyzer

#

And it spits out a class or struct instance containing your values

azure jewel
fresh salmon
#

Or, the class instances directly, serialized so you can set the values in the Inspector

#

Sprinkled with inheritance/interfaces to have a common point between all of these "stats"

azure jewel
#

i see i didnt think of that as a possibility

#

thanks for the answers

soft hawk
#

Or would I be better off with a Block[][] BlockArray
and copy it into a native array when I do multithreaded processes?

undone coral
#

persistent allocations need to be disposed

#

try using a regular array for now, and implementing a copy

soft hawk
#

ok

#

Thanks, didn't think about disposal

spare acorn
#

if i need help with making a 2d multiplayer game through photon engine do i ask in advanced?

spare acorn
#

aight

round eagle
#

Is this somewhere I can ask for help with debugging?

sullen dock
#

Hello, I am trying to become a "pro" in Unity. But not sure how to. I made some small projects but I want to make something bigger and learn about advanced stuff.
I heard about "modularizing so you can run modules without running a simulation". How can I archieve that? Where can I read about it / how can I google about it?

sly grove
#

it's a really odd thing to latch onto though

sullen dock
sly grove
#

Just work on ever more complicated games

#

all that stuff will come out of necessity

#

If you really want to see/apply that principle, I recommend making a virtual board game?

granite viper
#

modularizing so you can run modules without running a simulation
What does that even mean

sullen dock
granite viper
#

that sounds like a pain in the ass

sly grove
#

No I don't think it's that

#

I think it's more like, if you're making a checkers game for example, you'd basically build out a library of code that handles the whole checkers game simulation

#

without any GameObjects or visual aspects at all

#

and then you can use Unity as a presentation layer

#

But idk - it's worded kinda weirdly

granite viper
#

I've tried doing that, it's a pain in the ass 😄

#

imo not worth worrying about unless you're doing something hella complex

#

that isn't to say compartmentalization is a bad thing

sullen dock
#

I just want to become a better programmer and get hired

granite viper
#

best thing to do is build up a portfolio of projects

#

showcasing a decently wide array of abilities

sullen dock
#

I have a itchio profile with some game jams entries, but I want to learn useful stuff that companies want. Like design patterns, unit tests, etc. Making small projects won't teach me that stuff

sly grove
#

Silly corporate buzzwords valued over actual skill 😢

#

Unit tests are good though 😛

sullen dock
#

what about dependency injection

sly grove
sullen dock
#

I think that could be useful for me, since I always do a lot of work referencing objects between scripts.
I always do public GameObject anotherScript and drag and drop the other object in the editor. But not sure if that's the best way

sly grove
#

That's a really good way to do things generally

#

It's just not always possible

sullen dock
sly grove
#

it's a little less "noobish" to use [SerializeField] GameObject anotherScript; and even less noobish than that to use [SerializeField] SomeComponentType anotherScript;

#

It's relatively rare to have a good reason to reference a GameObject directly rather than some specific Component

granite viper
#

yeah, the most generic I usually do is to reference the Transform

#

if I'm doing placement things

coral citrus
#

Is it possible to have a shader reference variables from each point of a mesh?
https://i.gyazo.com/c89f041011c9c845b2338d448db971e7.png
https://i.gyazo.com/fdd287b7ca08787b3d97a9cc16160f15.png

^ Basically, I have a dye shader that's being applied to an animated skeleton that's all part of one mesh. It recolors the RGB channels of slots, bla bla bla, but the point is this:

  1. I could set materials per slot, but that has an absolutely enormous performance overhead.
  2. I could use a render separator for spine (the skeleton extension) but that severely restricts what can be dyed & means slots with the same slot have to all be on the same layer.

3. Ideally, I'd like to be able to just have the shader be applied to the entire skeleton's mesh renderer material and have it read the desired variables from each slot by vertex or whatever. Is that possible?

undone coral
#

what is the visual result you want?

#

you can associate a texture with your sprite that contains the information you need

#

then reference it in the material

#

what does it have to do with meshes in the pixel art?

frank peak
#

protips for namespace usage? sorry if this is a newb question lol

quiet bolt
#

...well, sort of

#

i can't build my project using that dll and this is the error i got:

ArgumentException: The Assembly System.Deployment is referenced by System.Windows.Forms ('Assets/Plugins/System.Windows.Forms.dll'). But the dll is not allowed to be included or could not be found.

#

wait, does this mean i need the System.Deployment dll too?

#

oh shit it actually works now

frank peak
#

noice

quiet bolt
#

@valid flame could be useful for you too. make sure you have the System.Deployment.dll file in your assets folder

valid flame
#

I have no context or memory of this conversation

quiet bolt
#

oh i thought you were still interested about the system.windows.forms thing

#

alrighty then

snow grotto
#

How would I SphereCast with an start and end point instead of a start and direction?

#

Like a line cast but with a radius

#

Solved it by doing this, still wondering if there is a better solution

midnight violet
snow grotto
#

Yes exactly, I was just wondering if there is a standard call that gives me the option to insert a start and end position

#

Unreal has the opposite were you can't fire a ray and you have to calculate the ray end position manually were in Unity you need to calculate the end position yourself

midnight violet
snow grotto
#

ye, using the direction magnitude was already clever since I need to calculate the direction anyways. Well thanks for the info, this will do for now

gaunt skiff
#

what I am doing is making a post request in an IEnumerator, then waiting for it to return a json string using another IEnumerator, then finally returning that string from the function that started those coroutines

fresh salmon
#

Errors because your getProfileJson coroutine is declared inside another method, so Unity couldn't find it

#

It will produce the same error for waitForJson

#

Take them out of the method and mark them private if you don't want them to be accessible from the outside

gaunt skiff
#

both of them are inside the Get method

fresh salmon
#

Yes, that is the problem

gaunt skiff
#

If I take them out I'll have to pass a string to getProfileJson

fresh salmon
#

Yes, that is the fix

gaunt skiff
#

okay lemme try

#

still getting that error

fresh salmon
#

Use return values, out parameters to provide values back to the caller method

gaunt skiff
fresh salmon
#

On what line is the exception thrown now?

gaunt skiff
#

46

#

same thing

fresh salmon
#

No idea, you'll have to debug it more. Also you have a flaw in your code, the lines

StartCoroutine(waitForJson());
Debug.Log("wait finished");

won't actually make it wait before running the Debug.Log, as StartCoroutine starts the coroutine and resumes execution right away

#

It's like a background task being started on another thread

gaunt skiff
#

oh

#

then how am I supposed to return string from IEnumerator?

fresh salmon
#

You have to wait for it by making Get() itself a coroutine, and every sub-coroutine you want to wait, you do yield return StartCoroutine(SubCoroutine()) for example

#

And you can't return anything from coroutines, so you have to store the state inside class fields

#

Like you have right now, the bool receivedJson

gaunt skiff
#

okay

midnight violet
#

You can always throw in a UnityAction as a callback that gets invoked on the end of your desired coroutine

undone coral
#

including web requests

green river
#

Hey y'all. Doing a whole Steam voice integration deal right now. TL;DR - I'm successfully sending compressed audio packets (of player's voices) to other clients who then decompress it and add the decompressed sounds to these float[] buffers. There seem to be 2 ways to get those float buffers into your spreakers. 1. Set up some kind of sound by making an audio clip and then sort of hacking the sound in PCMReaderCallback of the AudioClip or 2. writing an OnAudioFilterRead and just adding the voice into an audiosource as a custom filter (which runs on the audio thread). Ended up getting option 2 working as a proof of concept.

#

I think Option 1 would be better if I solved some issues with it. Was wondering if anyone knew of a good sample for just feeding floats into a running audio clip without it randomly turning itself off b/c it hits the end of it's data array or whatever.

undone coral
#

or a game with voice*

#

there are traditions

#

buffering sounds better

arctic robin
#

Hi.
If I have a cube parent that I want all child objects to follow, how do I scale the cube without having all the children be stretched around?

#

Is it possible to link transforms somehow?

arctic robin
#

Furthermore, what's the best way to use and highlight shaders that are stored in Packages? They don't show up in the inspector and when I menu dive down Packages I can't drag them onto the object. Am I supposed to drag stuff from Packages to Assets as needed?

fervent cave
#

Is there any way GraphicsBuffers can hold your custom struct?
seems like the issue is that sizeof(CustomStruct) fails,
adding [StructLayout(LayoutKind.Sequential)] doesn't work
also [StructLayout(LayoutKind.Explicit, ...)] doesn't work

agile yoke
#

Well, you can definitely hard-code the size and then it can hold the struct just fine. You can probably also use UnsafeUtility.SizeOf

#

You do need to make very sure the layout of the struct (and its size) matches what's expected on the other side.

fervent cave
#

I'll just go with SoA instead of AoS

#

so one GraphicsBuffer for each property

gilded wing
#

sort of a general C# question but is there a way to provide a capacity for an event Action ahead of time kind of like you can for a List etc. to avoid allocation when multiple things are added to it?

#

i know it's small and i'm not using them so much that it'd become an actual performance problem probably, but just as a matter of principle

agile yoke
#

Hm, you can manually implement the event (i.e. write add and remove) and back it with a list or something. I'm not aware of any way to tell the auto-implemented events to reserve capacity like that, but maybe someone else is.

gilded wing
#

hm yeah i might actually end up doing something like that, mostly because i get distracted by any spike on the GC graphs when profiling

undone coral
fervent cave
#

those are? im not targeting low-end devices

undone coral
#

there's a limitation on iphones

#

that's significant

#

it impacts a lot of unity assets that's why i know about it, i don't know what it is specifically sorry

sweet summit
#

Does anyone here have experience streaming audio data to FMOD?
I've got a nice voice chat system working using built in audio and need some help understanding how to feed data to a stream via pcm callback.

undone coral
#

sorry i didn't mean to be vague

fervent cave
#

yea that's not what im targeting, the buffers do end up being used within a compute shader tho

#

no worries 🙂

lunar oyster
#

Can anyone tell me which version of Visual Studio should I download for Unity? (Community 2022, Professional 2022 or Enterprise 2022)

fervent cave
#

be a vs code chad

sweet summit
#

You could use VS Code :P

undone coral
#

can you try System.Runtime.InteropServices.Marshal.SizeOf instead of sizeof @fervent cave

#

i think sizeof is an unsafe keyword right?

#

you can use structures in a graphics buffer

lunar oyster
#

I was just looking at a tutorial and he said to use Visual Studio

#

I'm new to Unity so...

fervent cave
#

im almost done implementing the SoA approach, if there's any issue with performance or portability ill look at changing it

sweet summit
undone coral
#

i'd prob google it since it's arcane

sweet summit
#

Fair, FMOD is audio middleware and has its own stuff going on.
Who is this marshal guy after all? Better not be related to json

agile yoke
fallen halo
#

guys, does anyone here know how to make a player detector for an enemy in a 2d platformer game. The enemy type is melee

fervent cave
#

wdym by player detector

sweet summit
#

You mean like allowing the enemies to reference and detect the player?

fallen halo
#

how do the enemy know if player is near

#

currently i am doing a raycast to the front of the enemy object. But what happens if the player jump. The player will be over the raycast but still very much near the enemy

fervent cave
#

you can define a radius for the enemies, then check whether the distance between player & enemy is within that radius

#

but with this approach enemies could detect the player through walls etc.

sly grove
#

with a tall enough box that the player can't jump over it

fallen halo
#

i see. There is a edge case that i just can't solve though?

sweet summit
#

What i do for detection in my game is one Detection script on the player.
The player has an overlapsphere around them that checks if the monster can see them and says "you can see me"
Its faster to check one player against all enemies instead of each enemy having hitboxes around them

#

The game also has sound mechanics with same principle, it does CheckVisibility(otherMonster, myVisibility), CheckAudibility(otherMonster, myAudibility)

#

The player sphere will touch everything through walls so you can get references to the monster, thats where you check line of sight and real max distance

fallen halo
#

What do i do in this case?
i want the player detector to not detect the player if there is a gap between them, because the enemy is a melee type that can't cross a gap.
In a case like this i want the enemy to act like the player is nowhere near. But how do i do that?

sweet summit
#

That has to do with their ai, yeah pathfinding

sly grove
#

you need a 2d pathfinding algorithm - if there's no path to the target you know it can't reach the player

fallen halo
#

i am using behavior tree that uses the player detector. so in this case the enemy can see the player and the behavior tree has the enemy idling on the edge.
i was thinking if i can do some other kind of player detection then i could update the the behavior tree accordingly so that the enemy doesn't sit idle on the edge when there is a player on the other side

unique ermine
#

Can I lerp from a higher number to a lower number?

slender stag
#
    {
        webcamTexture = new WebCamTexture();    
        Renderer render = GetComponent<Renderer>();
        render.material.mainTexture = webcamTexture;
        webcamTexture.Play();
    }```

So, I was using webcamTexture, I need to handle an error if Unity can't access the webcam. However, try-catch don't works because the error is native code neither simple checks like "webcamTexture == null" or anything. Is there anything that I can do to handle webcam errors?
unique ermine
# sly grove yep

isnt it then just
Mathf.Lerp(higherValue, lowerValue, Time); ?

sly grove
#

yes

fervent cave
#

how can I set a field of scriptable object to be readonly/constant once initialized. I create the object from a script and for some reason (or I have not found another way) ScriptableObject.CreateInstance<MyScriptableObj>(); doesn't call the underlying constructor. So if I have a readonly field in MyScriptableObj I can't assign to it

sly grove
#

best option is not to use readonly but to have properties with only getters

fervent cave
#

thanks, ill look into that new to c#

#

same problem as with readonly. I basically want to use a scriptableobject as data-container for a baked bit mask. I thought using scriptable objects are an elegant way to store them and make them inspectable within the editor

green river
#

new question folks

#

void OnAudioFilterRead(float[] data, int channels){

#

anyone know how to pre-predict the number of channels this will have

#

like... i'm always getting 2 channels but idk if i can rely on that... you know?

fervent cave
#

change an audio source to mono, channels should then be 1. I guess all your audio files are stereo

undone coral
#
[Serializable] struct BitMaskContainer {
  readonly BitMask bitMask;
  ...
}
undone coral
#

and implement it with the struct. keep the field private

fervent cave
#

thanks, what's Odin?

undone coral
#
class MutableBitMaskContainer : IBitMaskContainer {
 // inspector editable
 [Serializable] private BitMask bitMask;
 BitMask bitMask => m_BitMask;
}

interface BitMaskContainer {
 bitMask {get;}
}
undone coral
#

helps you write inspector windows for stuff like this

#

just easier to do

#

not sure if it supports this exact use case OOB though

fervent cave
#

actually really useful to have that as an attribute

#

you can still change the field within a script just not in the editor

undone coral
#

level 0: "how do i make these fields read only"
level 1: "why stress so much about access when i control all the source code? i can always give myself access"

#

don't move down the ladder! don't say performance!

#

don't do it!

fervent cave
#

well I did change the VFX package to make some class public xd

undone coral
#

it's not COMPILE TIME read only so there's no optimization

#

lol

#

C# readonly != compile time read only*

undone coral
#

your body arrived earlier than your brain did

#

access controls in your own source are API documentation

#

that's why in go, they use an uppercase or lowercase letter, rather than a keyword

#

jk they have no good reason for that it was a bad idea

soft hawk
#

Will burst compilation work if I make calls to external public methods that are non-static?

#
public readonly int2 BoardSize;
public bool WithinBorder(int2 destination)
    {
        return destination.x >= 0 &&
               destination.x < BoardSize.x &&
               destination.y >= 0 &&
               destination.y < BoardSize.y;
    }
    public bool IsEmpty(ref NativeArray<BlockParams> nativeBoard, int2 topPosition)
    {
        if (!WithinBorder(topPosition)) return false;
        return nativeBoard[VectorToIndex(topPosition)].BlockType == BlockType.Empty;
    } ```
#

I'm calling IsEmpty from a burst compiled method

zenith quarry
#

Hi guys. You probably know about nativeArrays which a great when you actually never want dispose it. I would like to have a nativeReferenceType like for Materials which never changes, so when switching Materials it just points to that new or old Material.
Would safe a Destroy(Material) on every switch because it copys the value and just leaves the old Material to the Gc. (which never gets cleaned so I destroy it on the spot).

How do you guys solve the issue to safe that destroy?

soft hawk
zenith quarry
#

Like here for example. I switch all the Materials to a glowmaterial (because it is cheaper than switching a boolean or glow value in the shader for many diff objects) which just leaves the old material for the gc and copys the values to a new material that gets assigned.

#

When I could use a nativeArray (for referencetypes) I could maybe just change the pointer to the references and never copy any values

undone coral
#

implement highlighting?

#

because it is cheaper than switching a boolean or glow value in the shader for many diff objects
i don't think that's true.

#

the glowing should be implemented as a feature of your uber shader, in shader graph

#

you would recreate the standard Lit material and add your Highlight Glow feature

#

and use that as your shader for your materials everywhere

soft hawk
#

I thought so :<

undone coral
#

i am pretty confident it will try to transitively compile

#

you should try though

soft hawk
#

Yea I'm trying, in the bug fixing stage hehe

zenith quarry
# undone coral the glowing should be implemented as a feature of your uber shader, in shader gr...

I have that approach for the Hextiles (material property block) which have a simple Shader and is faster but some Objects have multiple Materials and also Shader where this approach is slower.
Thats why I switch all the materials for the big Multimaterial Objects (which is faster than switching a variable via mpb even with the stupidly needed destroy(material))

What I want is pin down the Reference types (materials), so they don't move around in the heap and just switch pointers instead of copying values.

#

Unity has one, called transformaccessarray which is a godsend but it is only for transforms.

undone coral
#

i think you can use Renderer.GetMaterials(List<Material> m)

zenith quarry
#

Exactly I just want to change the pointers

#

Gonna try thanks

undone coral
#

it's really hard to tell

soft hawk
#

So NativeQueue doesn't copy, apparently.

#

I've wasted like 3 hours because NativeQueue doesn't copy 😦

zenith quarry
soft hawk
#

No, just my own thing

zenith quarry
#

Ah good^^. .GetMaterials sadly just copys the materials on the render into a list.

#

But I think I gonna figure it out myself how to use pointers and pinned down code

soft hawk
#

oof, good luck

soft hawk
jovial totem
#

How do I export and import shaders in an asset bundle? It doesn’t seem to work for me. I’ve heard something about shadervariants but I’m not sure how to use them in this way.

tough tulip
solid elm
#

Hi, i want to perform a 0-1 scaling on 3d sphere.
Let me explain, i am shooting a raycast on a 3d sphere and i want a method which can get a float number between 0 (center of spehere) to 1 (circumference or outerline of sphere) depending upon the raycasthit point (position). How can i achieve this.
I have tried calculating diffrence between the position of sphere and racast impact point, it works somewhat but is complex to implement in code. Is there any Mathf function or Vector functions which i can use to calculate this 0-1 scaling easily.

flat marsh
#

if you shoot a ray towards a sphere shouldnt the impact point always be on the spheres surface?

solid elm
#

yes i want to scale that surface to 0-1 in float number

#

so when i shoot i can get a number between 0 - 1 that specifies where the impact happen

frank peak
#

mathf.clamp01(valueToClamp)?

solid elm
#

i am not clamping any value

frank peak
#

isn't this what you want?

#

oh wait nvm

#

some googling found me this for scaling a value
var result = Mathf.Lerp (10, 100, Mathf.InverseLerp (1, 5, 3));

#

but youll need to look at what the lerp paramas are and plug in your range of values

agile yoke
#

You said "0 (center of spehere) to 1 (circumference or outerline of sphere)", but how does that work with a raycast? Sejadis' point was that a raycast from outside a sphere can never hit its "center", it always hits on the surface.

frank peak
#

var result = Mathf.Lerp (0, 1, Mathf.InverseLerp (minInput, maxInput, 3)); i think would work

#

oh lol

solid elm
#

@agile yoke my context is surface only

#

i can't find a proper way of doing it

agile yoke
#

Then you will need to try telling us again what you actually want. If you don't want 0->1 to be center->surface, what do you want 0 and 1 to mean?

solid elm
#

how can i get this point value from center to end

#

for now X- Axis only

river musk
#

So, sometimes what you want isn't what you need.

solid elm
#

i just made a pokemon ball 😂😂

agile yoke
#

Aha. In that case, if you're only interested in the X axis, you can calculate Mathf.Abs(hit.x - center.x) and then remap that from [0, radius] to [0, 1] by dividing it by radius.

solid elm
#

going to try it

novel plinth
#

Anybody knows a better alternative to check if a method was overriden or not? Faster than the below reflection would be nice

    private bool Overriden(MethodInfo method)
    {
        return method.GetBaseDefinition().DeclaringType != method.DeclaringType;
    }
river musk
#

I have a narrow box object like a tight rope. I use a trigger on the bottom of my player to start the balance walk over this area. But I need the player to be positioned in the center of the walk area. I don't want to use a position object on the box object, I want to somehow use code to calculate it. Is there a way to do this?

lucid girder
# solid elm going to try it

Since you are working with a sphere, and detect hit on it's surface, you can normalize the vector between hit and center. This will create a directional vector at length 1, which you can multiply with the radius to get the original position

#

A normalized vector will never exceed 1 for any x, y, z

agile yoke
#

True, if I'm not mistaken, Mathf.Abs((center - hit).normalized.x) should also be equivalent to what I said, with the added benefit of y and z being easy to access too.

solid elm
#

this seems way easy i can try

lucid girder
#

You probably don't want to use Mathf.Abs because you want to hit the left/bottom side as well

agile yoke
#

I was assuming they meant "0 to 1" literally and wanted a "distance from center" value. If they do want the direction, then leave off the Abs and get -1 to 1, yeah

tough tulip
lucid girder
novel plinth
#

I was resorted to this method due to how unmaintainable the project is, not only that, it's based on the older or rather ancient framework.. I found a better solution to this 🙂

thanks guys!👍

lost beacon
#

for saving fields, would you rather have

        this.SaveField(() => testVariable);```
or
```cs
        this.SaveField("anyKeyString", testVariable);```
novel plinth
#

you're looking for style points or just want to ask for opinions 🙂

#

whatever floats your boat

lost beacon
#

any reason to choose the latter

flint sage
#

Well, the first one would possible cause trouble with duplicate names

lost beacon
mint sleet
#

Hello.

#

I have a size of 1 GB .apk file on the cloud, and I need to download and save it into the persistence data folder to execute when it is finished.

#

I got Access denied on the editor when I try to write it to the C:/

#

do you have any starting point for me

fresh salmon
#

Directly writing to the root C:\ or in a subfolder?

#

Because I think writing to the root isn't allowed if you're not admin

devout hare
#

also that isn't "the persistence data folder" on any system

fresh salmon
#

Do they mean the roaming one? C:\Users\<user>\AppData\Roaming?

#

Or just anything under AppData

undone coral
#

Is there a way to run the profiler in standalone builds without the editor? Does anyone have experience with this?

drifting galleon
#

yeah that's possible

undone coral
#

How do people performance sample live games?

undone coral
#

Like the API for uploading a profiler report

#

Or if there’s a preexisting way to turn it into a more standard tracing format like chrome’s or jaeger’s

native plover
#

If we need a loop inside a coroutine, what's the point of WaitForSeconds() ?

drifting galleon
devout hare
#

A loop is for doing things multiple times. WaitForSeconds is for waiting before continuing the coroutine. The two aren't connected in any way.

sly grove
native plover
#

So a for loop speed isn't relative to the framerate

#

if I do for(float t = 0; t < duration; t+=Time.deltaTime)

#

It won't take "duration" amount of time

devout hare
#

Only if you yield return null inside the loop

sly grove
#

There is never any "waiting" in code unless it's in a coroutine and you ask for it to wait with a yield statement

#

Time.deltaTime is just a number, it doesn't do anything magical

rotund dagger
#

So what kind of coding needs to be done to produce the kind of painting shown in this trailer?

#

Runtime mesh/texture manipulation?

sage radish
somber swift
#

That’s most likely the case. Atleast with unity the most expensive part of manipulating textures using cpu is applying the changes. Changing few pixels on cpu isn’t really that expensive but the applying part is (well if the image is reasonable sized (something like 1000x1000) and the texture doesnt use mipmaps, youre most likely not having problems running the app at 60fps or so) . In any case gpus are much (really a lot) more optimized on this type of things

thin lantern
sly grove
#

That's what you've got to work with

thin lantern
#

used PrefabAssetType.Model and it worked ty

hushed sparrow
#

Ight so in this code (The List contains a list of scripts which then contain an abstract class for the AI) it saying the name of the coroutine does not exist in the current context, but it should?

#

all that it says is

#

i tried changing it and realized another issue, why is this script which inherits from monobehaviour not active?

somber swift
devout hare
hushed sparrow
#

wait i think i figured out the issue

#

i did

#

fucj

#

nvm i solved it it was really dumb and just a simple mistake on my part

undone coral
#

i am imagining

 1. a standalone player is built with
    [RuntimeInitializeOnLoad]
    static void StartProfiling() {
      SomeAPI.Profile(filePathForReport: "report.bin");
    }
 2. upload "report.bin" to server
#

surely this must exist

tough tulip
undone coral
#

this is really helpful

#

i can grep.app this 🙂

#

no

#

who am i kidding

#

nobody is this sophisticated writing open source code for games lol

tough tulip
undone coral
#

🤮

#

yeah this is metrics

#

but i want those sick stacks

#

i don't see the tracing (yet)

#

looks like they wrote their own tracing for build logger

#

and it doesn't use the Profiler tracing

#

they must have a tracing agent

tough tulip
#

Are you looking to profile building pipeline? Or trying to profile player?

undone coral
#

it's impossible to google for this stuff - "tracing"

#

i'm trying to profile the player

#

i was chasing a possibility that this code uses the Unity Profiler's tracing

#

but it does not

#

they wrote their own tracing... for some reason

hollow garden
#

why not just make one yourself

undone coral
#

i can definitely use jaeger's c# client

#

but unity already has a high quality tracer

#

i need the rendering instrumentation anyway

#

which i could not do myself

#

i'd have to e.g. fork HDRP and change all their calls to profiler

#

and that wouldn't give me that much in the end anyway

round pawn
#

if (!Application.isPlaying || points_buffer == null || (points_buffer != null && num_points != points_buffer.count))
Hi, this line in my compute shader marching cubes algorithm is giving me this error:

Parameter name: _unity_self```
I don't know what I should do to fix it, all I know is that `points_buffer` is the null value and google doesn't have much to offer on this situation.
#

points_buffer is a ComputeBuffer so if I initialize it early, it will be angry for poor garbage collection

#

It doesn't make sense to me that it would be so sensitive to whether points_buffer is null, because that case is accounted for in the if statement

#

Here's the whole method:

void CreateBuffers()
    {
        int num_points = points_per_axis * points_per_axis * points_per_axis;
        int num_voxels_per_axis = points_per_axis - 1;
        int num_voxels = num_voxels_per_axis * num_voxels_per_axis * num_voxels_per_axis;
        int max_triangle_count = num_voxels * 5;

        // Always create buffers in editor (since buffers are released immediately to prevent memory leak)
        // Otherwise, only create if null or if size has changed
        if (!Application.isPlaying || points_buffer == null || (points_buffer != null && num_points != points_buffer.count))
        {
            ReleaseBuffers();
            
            triangle_buffer = new ComputeBuffer(max_triangle_count, sizeof(float) * 3 * 3, ComputeBufferType.Append);
            points_buffer = new ComputeBuffer(num_points, sizeof(float) * 4);
            tri_count_buffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw);
        }
    }
undone coral
#

!Application.isPlaying this is toxic

#

are you Releaseing a null buffer

round pawn
agile yoke
#

@round pawn It throws that exception if you .Release a buffer and then later try to access .count on it.

#

Calling Release will not make it compare == null, so that check doesn't save you, but does make calling .count invalid.

agile yoke
#

You can either set your reference to null after Releaseing, or check IsValid() before accessing count I believe

undone coral
undone coral
#

is there a way to insert a one-time function execution in a DOTween sequence?

#

so as opposed to an oncomplete

#

it can happen at a specified time?

#

InsertCallback 🙂

solid elm
# lucid girder Since you are working with a sphere, and detect hit on it's surface, you can nor...

I applied your logic and it works exactly how i want it gives value from centre to raycast impact point (0 - 0.999) without multiplying the radius, can you explain why you said to multiply with radius, is it necessary. And one more thing the values in the normalize vector between hit and centre are negative also as it should be for x < 0f and y <0f, is there a way to always return positive value with some vector3 function or i have to manually check and multiply with -1 each vector value.

desert hollow
#

Hello, I recently jumped from unity 5.x to the 2021 version (Big Jump!) I am in the process of learning the new Unity.Netcode functions and the issue I am having now is that I cannot send GameObject references via ServerRpc calls. Does anyone have recommendations to get around this?
Unity 5.x worked:
void CmdThisGuy(GameObject objWithNetworkIdentity)
Unity 2021 Does not work:
void ThisGuyServerRpc(GameObject objWithNetworkObject)

buoyant vine
#
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;

namespace XUnits
{
    public class DatabaseTest
    {
        [field: SerializeField] private List<ScriptableUnitDatabase> databases { get; set; }
        [Test]
        public void DatabaseTestSimplePasses()``` ive got that code in a unit test script but it ( unity editor ) cant resolve ScriptableUnitDatabase BUT Visual studio can resolve it..
```using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace XUnits
{
[CreateAssetMenu(fileName = "UnitDatabase", menuName = "Units/Database")]
public class ScriptableUnitDatabase : ScriptableObject````

ivory swan
#

Hey everyone, I'm trying to make a card game just for funzies and I'm cracking my head open about how to create kind of generic ScriptableObjects that represent every possible kind of card that my game contains.

So, my cards are ScriptableObjects that have an effect, and this is the script representing the effect:

I wanted to represent the whole possible range of things a card can do here.

For example: A card that has condition "RaceCardPlayed", Suffix "All", Target "Race" and EffectTarget "Health" would read: When a X race card is played, ALL X race cards you control receive + Y health.

However, this doesn't really work as a single file would need to have space for all kinds of references, like possibly reference to health, damage, card, class, all units in the scene, available skills... not easily modular at all.

But creating different ScriptableObjects for different groups of effects don't really seem to work as well, since there are a multitude of groups of enums here that interact with each other, it's not really a vertical hierarchy such as "Card -> Battlecard" or "Card -> Spellcard". I would need "Passive -> RaceCardPlayedAllClassHealthEffectPassive" or things like that.

How would you handle this situation?

humble leaf
#

I'm currently working on a mobile game that requires the use of abilities, each defined with a bunch of properties (target type, sub stat to be used, etc.)

#

I handled it by creating the AbilityDefinition which also contains what I call templates. Objects which essentially store everything an ability can have, and I show/hide things you can change based on what the designer selects via enums.

However, this was really only possible (for me, since I don't really do editor scripting), with Odin Inspector.

#

You can see the list of sub stat modifiers (2 elements), but customized differently.

#

Another example I use this is with events in the game. Needed a way to "generically" define an event to be used, and more importantly the results of that event. Each option is a list of results EventOptionTemplate, which shows/hides properties based on the type (enum) selected.

#

So, that's all to say, the only way I've handled it was basically giving the SO all the properties of the definition and let the designer fill in what's needed. Then at runtime, you just make informed decisions based on those properties (if something was flagged true, or a specific enum was set).

carmine ermine
# ivory swan Hey everyone, I'm trying to make a card game just for funzies and I'm cracking m...

i would recommend reading this series of articles of recreating hearthstone:
https://theliquidfire.com/2017/08/21/make-a-ccg-intro/

generally his solution is to have an generic event system that any card can post a notifcation to, and any card can subscribe to any notifcation. so a card can subscribe to "if a race card was played", and if it was then activate the effect of buff health. i would make any effect like that a class, and then in the buff health class have an int to decide how much to buff health.

im currently working on understanding that system too so i dont know exactly how it works but it seems promising and scalable to me

#

i would generally make cards scriptable objects, and everything that can make up the cards can be classes/enums that you can include in the scriptable card fields

urban warren
#

Hey-o, I was wondering what the status of using Expression Trees at runtime was?
I was reading that they don't work on IOS, or maybe when using IL2CPP...? Or both? It wasn't really clear to me and was hoping for some insight.

ivory swan
# humble leaf So, that's all to say, the only way I've handled it was basically giving the SO ...

Thanks a bunch! Your system seems reaally nice and similar to what I'm trying to do. I was thinking exactly about finally giving in and purchase Odin, as I knew they have toggleable inspector thingies. I'm still not entirely comfortable with having basically all possible references inside the script and just have them "turned off" in the inspector, but your idea of having these template objects may be really interesting to have some sort of separation.

north fossil
#

I don’t understand the burst documentation. It says

“When running a Burst job in the editor, the first attempt to call the job will cause the asynchronous compilation of the Burst job to be kicked off in the background, while running the managed C# job in the mean time.”

I thought everything needs to be compiled before the program can even start. And even if it could, Wouldn’t it be best if it was compiled before the game even begins to prevent unnecessary slowdown in game?

austere jewel
# north fossil I don’t understand the burst documentation. It says “When running a Burst job ...

I'm not sure if this is exactly how it works as I don't have a great handle on how Burst compiles, but I would imagine that it's similar to non IL2CPP, where the code is compiled into IL, and then it is JIT compiled into machine code at runtime. This only happens in the editor so you don't have to waste time compiling things that are not used, and it's also cached—so it will only get recompiled if the IL changes.

north fossil
#

Ah, this option is for running the code in the editor, not the binary. Thank you

wise bobcat
#

hello

#

I am trying to load audio clip from raw data

#

raw data means compressed audio data

#

audio compression is Vorbis

#

i can only load it through Fmod native C++ code but i want to do it with unity

#

any help pls?

#

i am asking for 5 days continuously but no one is responding

#

i know Unity has the correct api to do this as well but there is no example for how to

granite viper
#

You can dig into the source or use it as is

wise bobcat
#

i dont just need vorbis

#

i want to support most likely all audio formats in UnityEngine.AudioCompressionFormat

#

except the mp3 format cuz its normal and can be read easily

granite viper
#

You said vorbis in your opening post :l

wise bobcat
#

sorry i forgot to say the whole thing

#

i want to dynamically load all compression formats

granite viper
#

Still, that plugin may give you some insights

wise bobcat
#

but i am out of ideas for how

#

ohk let me

granite viper
#

Hmm looks like it's a native plugin

#

So probably not

wise bobcat
#

yes its a native plugin

granite viper
#

As far as unity apis is concerned

wise bobcat
#

plus it takes audio clip as input

#

whereas i have bytes

granite viper
#

No it reads from path

#

So probably also has an endpoint for bytes

wise bobcat
#

it reads from the path and load as VorbisOGG

#

but i want to save the vorbis to mp3

#

like convert all compressed audios to mp3

#

and it can convert an audio clip to vorbis and save to filestream

#

which is something i really dont need

#

any ideas for how can i convert

#

i tried FMOD
But FMOD is in C++ and it is hard

final steeple
#

You can use ffmpeg to convert audio files

#

ffmpeg -i file.ogg compressed.mp3

#

Why do you want to convert from OGG to MP3 though? That will double-compress the audio and seriously harm the quality

granite viper
#

Looks like it supports reading anything in that unity supports

wise bobcat
#

i dont have audio type

#

i have audio bytes which are compressed

#

so audio compression is someway related to audio types

#

.ogg

#

.mp3

#

.wav

final steeple
#

If you want to determine which format the file is in, you can read the header

#

For example, if the file starts with four bytes corresponding to the ASCII string RIFF, it's probably a wav

wise bobcat
#

vorbis is most likely .fsb

final steeple
#

No, fsb is an FMOD Studio Binary

#

er, FMOD Sound Bank

granite viper
#

Can you decide whether my link works before you continue this debate

wise bobcat
#

ohk

final steeple
#

You can't load fsb files in Unity like that though

#

Not using the above API anyway

#

You would need to use FMOD for Unity to load those

wise bobcat
#

i am using FMOD

#

i also used FMOD factory

#

but it didnt work

#

all C++ native libraries

granite viper
#

I thought you were just trying to load audio at runtime

final steeple
#

I did too

wise bobcat
final steeple
#

No I thought that's what you wanted to do lol

wise bobcat
#

lol

#

its true i want to do that

final steeple
#

I thought you wanted to load OGG files, but you didn't know the format they were in

#

So you wanted to convert everything to MP3

wise bobcat
#

no

#

if it were the audio type then i have a complete enum that specifies the format

#
                {
                    case AudioType.ACC:
                        return ".m4a";
                    case AudioType.AIFF:
                        return ".aif";
                    case AudioType.IT:
                        return ".it";
                    case AudioType.MOD:
                        return ".mod";
                    case AudioType.MPEG:
                        return ".mp3";
                    case AudioType.OGGVORBIS:
                        return ".ogg";
                    case AudioType.S3M:
                        return ".s3m";
                    case AudioType.WAV:
                        return ".wav";
                    case AudioType.XM:
                        return ".xm";
                    case AudioType.XMA:
                        return ".wav";
                    case AudioType.VAG:
                        return ".vag";
                    case AudioType.AUDIOQUEUE:
                        return ".fsb";
                }```
#

for audio type 0

#

it would be m4a

#

but i am using Compressed audio

final steeple
#

I'm not sure why this matters, do you have more information on what you're doing?

wise bobcat
final steeple
#

Do these audio files originate from within your project or something?

wise bobcat
#

loaded from raw serialized bytes

final steeple
#

Then just reference the AudioClip?

#

There's a communication error here, I thought you had something like:

game/
    game.exe
    game_Data/
        StreamingAssets/
            sound.ogg
#

and you wanted to load sound.ogg

final steeple
#

Then is the audio file in your project, in Assets?

wise bobcat
#

i am trying to load all audio compressions in unity on runtime

#

let me show something

#

here is a library that allows you to load texture 2d from any texture format and saves it to directory as a .png

#

done by me

#

same work i am trying with audio clips

#

compressed one

final steeple
#

So you have an AudioClip and you want to save it to a file at runtime then?

wise bobcat
#

like changing their compressions

wise bobcat
#

i have raw bytes of an audio clip which is serialized

#

most likely audio data

final steeple
#

How are you getting these bytes?

granite viper
#

I'm so confused

novel plinth
spare pond
#

Hello. I'm creating a LimitedList<T> : List<T> class with the int Limit property. How do I serialize it so that it is displayed in the inspector? Do I really need to create a custom drawer?

granite viper
#

You need to add the Serializable attribute

#

To your cladd

#

Class

spare pond
#

Yea, I already discovered that

final steeple
#

TIL you can use FLAC in Unity natively, just do (AudioType)7

#

I noticed that AudioType actually maps directly to the FMOD_SOUND_TYPE enum

#

Which has FMOD_SOUND_TYPE_FLAC defined as 7, then I looked at AudioType in the reference sources and it's indeed there, just commented out

#

I assume it's commented because either
A. They don't support FLAC on platforms that don't use FMOD
B. It wasn't exposed originally so nobody has gone through the process to make it a public API

#

I tested and it works perfectly fine in both editor and build on Windows at least

final steeple
tough tulip
# wise bobcat i am trying to load all audio compressions in unity on runtime

if its a serialized encoded byte[] you would need to decode the audio samples to raw audio (uncompressed PCM)
for wav files its simple since the uncompressed audio is directly available after first 44 bytes (header).
https://docs.unity3d.com/ScriptReference/AudioClip.SetData.html

you can alternatively use UnityWebRequest to get the audio clip itself directly. but this is limited only for a file/url
https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequestMultimedia.GetAudioClip.html

if you're creating a library, saving to file and unsaving would not likely be an option for you

#

also beware of the bits per sample in Unity. many audio formats still store the audio in 16bits per sample, but unity expects a 32bits/sample (floating pt)

urban warren
#

I have a clarification question.
If I have a interface with methods that take/return System.object, and I implement them in a generic class with generic overloads. And then I have a variable of that interface assigned to an instance of the generic class.
When calling the methods, does it use the generic ones if possible?

final steeple
#

Yes

#

To call the object overload, you need to pass in an object, meaning you'll need to cast in most cases

#

There are exceptions though, mostly related to constraints and multiple type parameters

#

When in doubt, hover over the call in your IDE

urban warren
# final steeple Yes

Right, so this would be correct?

interface IGetSet { object Get(); void Set(object value); }

class GenericGetSet<T> : IGetSet
{
  public T Get() { .. }
  public void Set(T value) { .. }
  
  object IGetSet.Get() { return Get(); }
  void IGetSet.Set(object value) { Set((T)value); }
}

// In some class...

IGetSet _getSet = new GenericGetSet<float>();

// This will use the generic imp and avoid boxing correct?
_getSet.Set(0.5f); 
final steeple
#

No, that will call the non-generic implementation

urban warren
#

Dang it...

final steeple
#

You will need another IGetSet<T> interface, and use that

#

Or just use GenericGetSet<T> directly

urban warren
#

Yeah, that won't work for my use case as I don't know the type

final steeple
#

Then yeah, you can't call the generic version

#

Generics require you to know the type

#

You can avoid the boxing though, with a bit of work

urban warren
#

Oh?

final steeple
#

You need to implement a Variant type

#
public readonly struct Variant
{
    readonly object typeOrValue;

    readonly VariantUnion value;

    [StructLayout(LayoutKind.Explicit)]
    struct VariantUnion
    {
        [FieldOffset(0)]
        public int Int32;

        [FieldOffset(0)]
        public float Single;

        [FieldOffset(0)]
        public double Double;

        // etc
    }

    public Variant(float value)
    {
        typeOrValue = typeof(float);
        this.value  = new VariantUnion { Single = value };
    }
}
#

You would use Variant instead of object

#

Then you can implement cast operators on this

#

To store a class in a Variant, you'd store it in typeOrValue

#

if typeOrValue is a Type object, the value is in the union

granite viper
#

Clever approach

#

I tried using variants ages ago but it went over my head at the time

urban warren
# final steeple You would use `Variant` instead of `object`

Never heard of variants before, I was just looking them up, but this is great.
This is quite interesting, it isn't quite clicking for me though. I think I have two questions, firstly, why store the type? And secondly, if you have an object value, you would still need to box it correct?

final steeple
#

If you don't store the type, you don't know what's in the variant

urban warren
#

Oh of course, you need the type for getting the value back out

final steeple
#

There is an example implementation you can look at

#

And secondly, if you have an object value, you would still need to box it correct?
If you have an object, it is already either a boxed value or a reference type

#

The idea is that you would use Variant everywhere instead of object, which will avoid boxing value types

#
public interface IGetSet
{
    public Variant Get();
    public void Set(Variant value);
}
urban warren
#

For insight, my usecase is that I will be getting/setting 'base types' (int, float, bool, Vector3, etc.) via reflection (or actions and functions)

final steeple
#

If you're doing this via reflection, you cannot avoid the boxing

#

At least, not in many cases

#

Reflection is super allocatey with few exceptions

granite viper
#

Presumably there'd be some kind of lambda compiling

final steeple
#

At which point I have to wonder if maybe this should be approached differently

#

Since that's not super AOT friendly

granite viper
#

I think this is editor only?

final steeple
#

If it's editor-only you have more options yeah

granite viper
#

You're doing SO variants right

urban warren
#

Yeah, that is what I thought. No, it is runtime sadly

urban warren
final steeple
#

Do you have more information on the scenario?

granite viper
#

Ohk

final steeple
#

What types are you wanting to set values on? What do they look like? Etc

#

Do you control the classes/structures you're working with?

urban warren
#

Yeah, I am working on an editor tool that lets you connect up properties of different class so that you can have them drive each other. So, if you have a WindController from one asset, you can have it's WindStrength property control the wind setting in your audio controller and you sky and water material etc.

#

So it will only be working with numeric types, and maybe bools.

granite viper
#

Why do generics and not just have a serialized object like class with boolvalue, intvalue, etc

urban warren
#

Generics in no way are required

granite viper
#

I think just doing a so type thing would work fine

#

Variant is like that but a bit more space efficient I guess

urban warren
granite viper
#

Doing an SO type thing

#

Serialized object

#

Sorry, typing on my phone

#

Not the best way to talk about code lol

urban warren
#

lol

urban warren
#

@final steeple Thanks for letting me know about that variant (pattern?). It solved an issue I was having in a much cleaner way than I was.

Not related to that, but man are delagates fancy, they can take simple GetValue reflection code from like 21ms to 3ms (over 10k iterations)

#

(The variant will let me setup math operations really easy!)

final steeple
#

They're pretty easy to get used to and very efficient

urban warren
#

I was going to have like classes with an array of the value and then add/subtract/multiply/divide methods you would override and all sorts of stuff. This is so much cleaner haha.

#

Random thing, but can anyone explain the syntax for operator overloading and implicit casting?
To me the ordering of the keywords seems nonsensical and inconsistent. Am I missing something for why it makes sense and is logical?

drifting galleon
#

example?

urban warren
#

To me it seems like it should be public static operator Data +(Data a, Data b) {.. }

#

As that would make it consistent with implicit conversion public static implicit operator Data(float f) {.. }

final steeple
#

You could consider operator+ the "name" of the function

drifting galleon
#

the difference is, with implicit, you don't care about any operator so theres just 'an' operator. with operator overloading you care about what operator to overload operator + not operator Data

#

and if you go after 'normal' c# method declarations........you can't start a method name with a non-word character

urban warren
final steeple
#

Not quite, implicit is a modifier, like unsafe or checked/unchecked

drifting galleon
#

+1

final steeple
#

For an implicit or explicit operator, there is no "name" only a return type, hence why that's used as a "name"

drifting galleon
#

a better question is: why is it not possible to declare methods only differentiated by the return type???

final steeple
#

Because the return type is not part of the signature in IL

#

Why isn't it? Couldn't tell you

#

Same goes for generic constraints

drifting galleon
final steeple
#

Maybe I was misremembering and thinking of constraints then

urban warren
final steeple
#

But either way the syntax would be pretty weird since you could only call such methods by casting the result or relying on target-typing

drifting galleon
final steeple
#

It's not an optimization problem, really

#

It's just weird-looking syntax and non obvious

#

I think overloading on return type would be very useful, don't get me wrong

#

but there are syntax problems to work out for sure

drifting galleon
#

🤷

final steeple
#

That said, I suppose there is "prior art" here

#

stackalloc works like that

drifting galleon
#

yeah

final steeple
#

stackalloc can give you either a T* or a Span<T> depending on the target type

#

(and also whether it's used in an expression or not)

urban warren
final steeple
#
var a = stackalloc byte[1]; // byte*
var b = (stackalloc byte[1]); // Span<byte>
var c = (Span<byte>)stackalloc byte[1]; // Span<byte>
SomeMethod(stackalloc byte[1]); // always Span<byte>
drifting galleon
final steeple
#

Because Span can refer to managed memory, which can be moved by the garbage collector

#

Since Span can refer to any kind of memory, it needs to account for that in its API

drifting galleon
#

ah, right

final steeple
#

So if you need a pointer, you need to ensure it's pinned

#

If you know that the span is pointing to memory that is already pinned though, you can do Unsafe.AsPointer(ref MemoryMarshal.GetReference(span))

#

Which will avoid any overhead of fixing

drifting galleon
#

nice

#

and i really need a 'simple' fixed statement. if you have to pin 5 or more types, the indentation is killing the code

final steeple
#

(on that note, everything is technically pinned always in Unity, because the GC used by Unity (Boehm) doesn't do any compaction of the heap, and thus nothing moves)

#

don't rely on that if you ever want to move to a version of Unity using CoreCLR though lol

drifting galleon
final steeple
#

You can have fast paths for it, which I do in a few places

#

You just have to guard it behind an "IsUnityMono" check

#

Most of the time it's more effort than it's worth though

drifting galleon
#

bleargh

final steeple
#

You'd only want to do it in a really hot path

final steeple
#

A lot of the time you can avoid the need to pin altogether using MemoryMarshal APIs

#

A simpler fixed like there is for using has been proposed before, but if I recall correctly it was rejected because pinning is generally something you want to be short-lived

#

Having the simpler syntax would mean more code fixing addresses longer than necessary due to the lack of blocks

drifting galleon
final steeple
#

Ah, yeah a lot of that code didn't actually need to fix anything at all

#

But there was a lot of code and I was worn out so I didn't bother getting into the specifics lmao

#

For the most part though, stackalloc + using pointers and avoiding marshalling would help significantly there

drifting galleon
#

yeah, i may look into that. it's fine for now. but still, a using like - simple fixed would still be nice, roslyn doesn't have to recommend using it, but i pretty much have to pin for the entire duration of the method, so it'd help

final steeple
#

If you need to do that, you can have an overload that takes pointers

#
public void A(ref int a, ref int b)
{
    fixed (int* pA = &a)
    fixed (int* pB = &b)
    {
        InternalA(pA, pB);
    }
}

void InternalA(int* a, int* b)
{
}
drifting galleon
#

.......which shifts the pinning to calling code.....which i also don't want

final steeple
#

No? This is internal to your method

#

The public API is unchanged

drifting galleon
#

oh wait. ahh i see

final steeple
#

I've used that approach several times, usually when interacting with native APIs that take a lot of strings

drifting galleon
final steeple
#

Nope

drifting galleon
#

sadge

#

but, .... any way to stack-allocate-only string?

final steeple
#

Sort of, it depends

drifting galleon
#

yeah......not getting around pinning memory then

final steeple
#

How long are these strings?

drifting galleon
#

about 20 chars prob

final steeple
#

oh you can definitely do that on the stack

drifting galleon
#

but variable length

final steeple
#

yup, span helps there

drifting galleon
#

ok, so how? using char[] instead of string?

final steeple
#

writing up an example right now

#
Debug.Assert(input.Length <= 15);
var buffer = stackalloc char[16]; // 15 + 1 for null terminator
input.CopyTo(new Span<char>(buffer, 15));
buffer[input.Length] = '\0';
// pass buffer pointer to native
#

that's to fit a maximum of 15 chars

#

increase as necessary

drifting galleon
#

ah, ok, imma try that.

final steeple
#

Basically you just copy the data you need into the stack and pass that along

#

Which can be more efficient for small amounts of data

drifting galleon
#

:/ just noticed you can't json serialize ref structs

final steeple
#

Yeah, ref structs can't be used in generics either, because it would allow them to be boxed

#

If you need to serialize it, it probably shouldn't be a ref struct to begin with

#

What does this ref struct contain?

drifting galleon
#

i mean i'd like to, it's small enough for ref struct probably, and it would also be more secure for the data. but i have to (de-)serialize from and to json

final steeple
#

Why does it need to be a ref struct and not a normal struct?

drifting galleon
#

so it won't be allocated on the heap

final steeple
#

structs are only allocated on the heap if you choose to allocate them there

drifting galleon
final steeple
#

If you really want to serialize it to/from json, you can have another struct that contains the actual data but is private, and you serialize that

#
public ref struct A
{
    Storage storage;

    public int Value
    {
        get => storage.Value;
        set => storage.Value = value;
    }

    public static A FromJson(string json)
    {
        // ...
    }

    struct Storage
    {
        public int Value;
    }
}
#

But all that said, I'm not really sure it has to be a ref struct here

#

If you pass it by value, it's already pinned

#

If you pass it by ref, you can just pass it by pointer instead to ensure the values you receive are pinned

drifting galleon
final steeple
#

That's not true

#

A ref struct is identical to a normal struct except:

  1. It can only be stored on the stack or in unmanaged memory
  2. It is allowed to contain byref-like fields (such as a Span<T>)
  3. It cannot be boxed as a result of #1, and therefore cannot be used as a generic parameter (because the ref struct-ness information is lost)
drifting galleon
#

my bad. i just tested it. but i could've sworn ref structs were only allowed to have ref struct fields....

final steeple
#

Only a ref struct can contain a field of a ref struct type, that much is true

#

But a ref struct can still contain any other type of field

drifting galleon
#

right

final steeple
#

I still hate that it's called a "ref" struct

#

Because it's not passed by ref

#

It just means that it's allowed to contain ref-like fields

drifting galleon
#

i don't mind the ref

final steeple
#

This confusion has been propagated to Unity's multiplayer code, in documentation they imply that they're passed by ref

#

Which is outright wrong

drifting galleon
#

what?

final steeple
#

Let me find the snippet

#

Ref structs help enforce both of those rules: they can't out live the stack context in which they were created, and they're always passed by reference no matter what.

#

Which is just... completely wrong

#

I hope that's just a documentation mistake and they don't actually think these are being passed by ref...

drifting galleon
#

thats.........terrible

#

i'm not so sure that that's 'just' a documentation error

final steeple
#

Yeah :(

#

I'm tempted to report it on the netcode repo

drifting galleon
#

pls do

final steeple
#

I first noticed this months ago lmao

#

Just completely forgot to get around to reporting it

drifting galleon
#

hmmm....anyway, i'd like the public api to disallow saving the data in a class which would put it on the heap. -> bad for security and would bug out memorymarshal

#

that's why i was thinking about ref struct

final steeple
#

As long as the input API takes pointers it's safe, but that's up to you as an API author

#

Since the native API holds onto the pointers you give it (I assume), refs aren't safe since they'll only be pinned for the duration of the method

#

I suppose there's also the option of internally storing a pointer, and you just have a struct wrapping it

#

Which would make it safe to store anywhere

#

But then you need to allocate and free the memory manually

drifting galleon
#

nah, i can imagine that being a back breaker

final steeple
#

It's a bit of a pain, yeah

#

I suppose a SafeHandle would make it not too bad, but eh

drifting galleon
#

and, i don't want to store it anywhere. only the stack

final steeple
#

Then yeah, you'll need to have a proxy type if you want to serialize it

drifting galleon
#

yeah. i'll try some things and see how it goes

drifting galleon
#

sorry to bother you again but how can i do this:

public ref struct MyRefStruct
{
    public MyRefStruct()
    {
        Type = stackalloc char["myString".Length]; //this does not work
        "myString".CopyTo(Type);
    }

    public int Alg { get; set; } = -7;
    public Span<char> Type { get; set; }
}
final steeple
#

You need to take the buffer as input, rather than allocating it in the constructor

#

Also you generally don't want to do a "dynamic stackalloc", always prefer a constant length

drifting galleon
#

but my strings are variable length

final steeple
#

Yes, you need to allocate a buffer of the maximum size

#

and then slice it

#

a variable length stackalloc is much more expensive than a constant one

drifting galleon
#

oooof. call that memory waste

final steeple
#

It's memory that you can't really avoid "wasting" without paying a significant cost

drifting galleon
#

that could easily turn into a stackoverflow

final steeple
#

You will be more likely to stackoverflow with a dynamic stackalloc

#

Check out the internal ValueStringBuilder type for an example of how this is often done:

drifting galleon
#

unlikely. because my strings might very well be shorter, not longer than 20 char

final steeple
#

Either way, you should always stackalloc 21 chars in that case

#

(You need an extra char for a null terminator)

drifting galleon
#

do i? i don't really care for termination

final steeple
#

If you're passing a pointer to native code you do

drifting galleon
#

damn

final steeple
#

Otherwise it can read out of bounds

#

There is one exception and that's if the API also takes a length for the string

#

But in general you'll want to always null terminate for safety

drifting galleon
#

anyway, how is dynamic stackalloc more expensive than 'arbitrary cost number' stackalloc?

final steeple
#

Because it can't be optimized statically

drifting galleon
#

ah

final steeple
#

And it requires more code to perform

#

Look at the JIT output for a dynamic vs static stackalloc on sharplab

drifting galleon
#

yeah i should do that XD

drifting galleon
#

yeah. can see that

wise bobcat
#

I have 2 libraries
one is x86 and other is x64

#

i want to add both

#

how can i do so?

final steeple
#

Typically you'll have a threshold where instead of the stack, you switch to a heap buffer (pinning it if necessary)

final steeple
drifting galleon
#

something else: does a literal string "myString" for example, already contain the null terminator or do i have to ad it? couldn't find anything on the internet

final steeple
drifting galleon
#

ok, good

final steeple
#

However the null terminator is not reflected by Length and is otherwise "hidden"

drifting galleon
#

yeah

final steeple
#

It's basically just there to help you when you're working with native code/pointers

drifting galleon
#

you cannot stackalloc ref structs???

final steeple
#

You can, but only as a pointer

#

because getting a span would require generics

#
var ptr = stackalloc MyRefStruct[500];
DoSomething(ptr, count);
drifting galleon
#

bleargh. lets. please. support. ref. constraints.

final steeple
#

allow T : ref struct will probably happen in the next C# version

drifting galleon
#

11?

final steeple
#

Yeah, I believe so

drifting galleon
#

i hope so

final steeple
#

tracking issue

drifting galleon
#

that should allow stackalloc-ing ref structs then, right?

final steeple
#

it's scheduled for .NET 7 which places it in C# 11

#

yeah, because the issue isn't that you can't stackalloc them, it's that they can't be used in generics and therefore you can't use a Span<RefStruct>

#

So that will "just work" as a result of fixing this

drifting galleon
#

too bad. not available in preview yet

final steeple
#

It's not even implemented in the language yet, still being designed

drifting galleon
#

yeah XD

final steeple
#

At the moment the syntax seems like it will be allow T : ref struct

#

but there's no guarantee yet

drifting galleon
#

allow T : ref struct ? shouldn't it be where T : ref struct?

final steeple
#

No, because it's not a constraint

#

It's the opposite of a constraint

drifting galleon
#

ahh, yeah makes sense

final steeple
#

Similarly, there may be allow T : static at some point

drifting galleon
#

tf does that do?

final steeple
#

To allow static classes in generics

#

Which would be useful once they can implement interfaces with only static members

drifting galleon
#

ahhh,

#

ok, sometimes i just cannot understand roslyn. i am stackalloc-ing a ref struct to a pointer, the ref struct only has value types and span, and my stackalloc is complaining about: 'cannot take address of managed type myRefStruct'

final steeple
#

If the ref struct contains managed references (which is what a Span is), then you can't get a pointer to it yeah

drifting galleon
#

wait what? but span is ......... ref struct

final steeple
#

A span is a ref struct containing a ref and a length

#

a ref is managed

#
ref struct Span<T>
{
    ref T reference;
    int length;
}

is a rough definition for what Span is

drifting galleon
#

yeah i know........but i have no managed type in my span stackalloc myRefStruct[] which contains Span<char> type = stackalloc char[16]

final steeple
#

You'll need to change that struct to contain char* instead of Span<char>

#

or make your own UnmanagedSpan<T> type

drifting galleon
final steeple
#

But if you need to stackalloc a struct that itself contains a span, that seems suspicious

#

I'm assuming you want to pass MyRefStruct to native code

#

In which case it shouldn't contain a span

#

because a span can't be sent to native code

#

(the pointer within the span can, if pinned)

drifting galleon
#

no. it's just the json tree. it's made up of multiple objects, which are nested in each other. i'm only ever passing specific values from those to the native interop structs (which take pointers 90% of the time)

final steeple
#

Do you have a more complete example of the types? It's almost 3am so my brain is having a hard time visualizing the whole thing lol

#

Ah in this particular case you probably can't avoid the fixing of those strings specifically

drifting galleon
#

and currently i feel like i just started programming XD

final steeple
#

Not without a lot of effort at least

#

public Span<char> Attestation { get; set; } = stackalloc char[7];
MonkaW

#

I had no idea that worked

#

I mean, it makes sense, but wow

#

TIL

drifting galleon
#

it does work

final steeple
#

It might be easier to implement this whole thing without worrying about the ref struct problem at first

#

and then you can look at transforming some types into ref structs after

#

Since right now there are a lot of unfortunate limitations that can make heavy ref struct usage a major pain to write

drifting galleon
#

yeah, i can feel that

#

but yeah thanks anyway. maybe i'll get around to ref-struct-ifying this eventually, but for now i guess i'll keep fixed-ing my types

final steeple
#

np

drifting galleon
#

and i don't want to keep you up longer

final steeple
#

It's definitely a struggle learning all this stuff lol

#

I wrote some REALLY bad interop code years ago

#

Eventually it comes naturally though

#

I actually noticed some of my older crappy repos getting forked recently, had to go archive them and add notes about them being bad code lmao

drifting galleon
#

well, i mean, i don't have that many problems with writing the interop, but the improvement and not fixed-ing everything would've been nice

final steeple
#

Yeah I just mean figuring out how best to make use of ref structs and all of the adjacent features

drifting galleon
#

def

#

the thing is, i am writing PInvoke code for api's microsoft doesn't actually want you to PInvoke or work with at all. (don't tell 'em XD)

final steeple
#

lmao

drifting galleon
#

and so the great new source generator project (CSWin32) is not particularly helpful with this api. no documentation, just plain c structures, nothing else

final steeple
#

I actually tried to google some of the functions when you posted the other code and it definitely seemed like a new API

#

There were almost no results at all

drifting galleon
#

it's not new. it exists since .........i think 2017?

final steeple
#

Weird

#

I'm surprised there was so little then

drifting galleon
#

like i said, it doesn't seem like microsoft want's 'normal' devs to use this api

#

and this has been a side project for me for about 4 years now, but every time i found a lead on how to possibly use it in standalone applications, that lead died out after a few weeks, most sources / api end points getting deprecated pretty much right after i found them (had nothing to do with me though, just normal lifecycle) until i finally found my new lead about a week ago and this actually seems like the way to go

#

hooray

tender badger
#

I think I should probably put this here, as it's turning out that this issue is much harder to solve than I thought it would be, and #archived-code-general Seems to be more for generic small questions instead of large issues like this.

#

Let me rephrase what I said in that channel:

#

So, I'm making a 2D pixel art game where you can fly around in a space ship in a randomly generated galaxy and do various different things.

#

Space is big. It's vastly, hugely, mind-bogglingly big. So to have a game environment that fits this famous quote I wrote a generator that generates a random galaxy based upon a couple of variables and a whole bunch of math.

#

Now, the problem is with rendering it.

#

This is a render of a galaxy with 25000 stars:

frank peak
#

break it into chunks and load the chunks? the implementation of this is up to you tho and might be tricky depending upon your generation code

tender badger
#

You can see the issue with this if you look at the top part of the image. Rendering this seems to be very expensive, and the framerate suffers from it. For more context, these are all rendered as 2D sprites.

frank peak
#

oof

#

hmm

tender badger
#

Preferably I would like to have it be somewhat stable up to 100000 stars. More if possible, but I would be happy with that. Right now, not even 10000 stars runs at a stable 60FPS. I've done some test, and to get a mostly stable 60FPS you can only have up to 3000-5000 stars. For the record, I have a Ryzen 5 2600 and RX 570 8G.

frank peak
#

are the sprites sprite renderer set to individual or chunk mode? that can make some different

tender badger
frank peak
#

maybe thats a tilemap only thing hmm

#

its usually on the sprite renderer but i only see it on the tilemap renderer

#

yeah nvm its a tilemap thing

tender badger
#

Yeah, that looks like a tilemap thing.

frank peak
#

how are the sprites organized, are they just individual sprites

somber swift
tender badger
#

I have a prefab GameObject. In the Start() method of the renderer, it goes through all of the stars and sets properties such as the size, color, a different texture for certain star types, etc.

tender badger
#

I just tried blindly following a tutorial (I know, bad thing to do), and of course that didn't end up leading anywhere.

frank peak
#

it goes thru what it means too

tender badger
#

It's one of the first search results, I watched it and it doesn't apply.

#

The thing is, all of these tutorials need me to input some kind of mesh into their game instancing, but I don't have a mesh, I'm using sprites, not 3D models.

granite viper
#

What's your problem?

#

Too many draw calls?

somber swift
tender badger
granite viper
#

Or too many objects

#

Make sure dynamic batching is on

#

Check the frame debugger to see why things aren't getting batched

frank peak
#

I think you need a custom material

#

what material are you using for you sprites

#

cuz if you look here at the material panel theres a checkbox for gpu instancing

#

but its unchecked and unavailable for the default materials (ie like the lit sprite material from the 2d extras pack or w/e)

tender badger
frank peak
#

ah okay

tender badger
frank peak
#

maybe if you make a custom material derived from the material you're using and just turn on gpu instancing then youll get the perfomance gains you want?

tender badger
#

I tried that, but I couldn't find the default material in any of the packages.

#

I also tried creation a new material, and changing nothing except for GPU instancing, but that actually halved my FPS and made it so the sprites don't render anymore.

frank peak
#

oof lol

#

how do i regenerate my packages folder? it seemingly empty all of a sudden, even stuff like URP isn't there lol

#

even tho it still works in game/im using the urp Sprite-Lit-Default material?

#

ah nvm you can just right click > create > material then set the shader to the default-lit-sprite material and enable gpu instancing

urban warren
#

Man, there doesn't seem to be a way to speed up getting/setting values of fields via FieldInfo without using Emit/ExpressionTrees :/

granite viper
#

yeah, basically

urban warren
#

(This wouldn't be a problem for me if people actually followed C# guidelines and didn't create public fields)

final steeple
#

There technically is for blittable types

#

But not for classes or non-blittable structs

#

Well actually in Unity you can

#

UnsafeUtility.GetFieldOffset

granite viper
urban warren
final steeple
#

Marshal.OffsetOf will give you the offset of a field in a blittable struct

#

But Unity offers UnsafeUtility.GetFieldOffset which works for everything

granite viper
final steeple
#

lmao

granite viper
#

there's so many nooks

urban warren
final steeple
#

You get the field offset, and then assign the value at that offset using unsafe code

#

Doesn't get much faster than that

#

It's basically a direct field assignment

urban warren
#

And potential draw backs?

granite viper
#

drawbacks is that it's unsafe

#

so you can blow yourself up

final steeple
#

That's about it, yeah

#

As for learning about it, I don't really have any resources on-hand

#

Basically the logic is just, if you have the offset to the field, you know where it is in the object

urban warren
final steeple
#

So you can just get a pointer to the object, add the offset, and set it

granite viper
#

yah, put on your bomb defusing gear and dive in

final steeple
#

So let's say we have

#
class TestClass
{
    public int ValueA;
    public int ValueB;
}
#

We want to set ValueB via reflection

#

but that's slow

#

Let's say we have a FieldInfo for ValueB

#

You can call UnsafeUtility.GetFieldOffset with that to get the offset

#

From there, you can do:

#
byte* addr = null;
UnsafeUtility.CopyObjectAddressToPtr(obj, &addr);
*(int*)(addr + offset) = 600;
// ValueB is now 600
#

Keep in mind that since this doesn't pin the object, it's only safe in Unity where the GC doesn't move objects (this will change when Unity moves to CoreCLR)

#

There is a way to do it without that problem by either pinning the object, or using the Unsafe class, which requires an extra DLL since Unity isn't using a version of .NET with that class built in yet

final steeple
#

Only if you use that code outside of Unity

urban warren
final steeple
#

The safe way is:

#
ref int valueB = ref Unsafe.AddByteOffset(ref Unsafe.As<StrongBox<int>>(a).Value, (nuint)o);
valueB = 600;
#

"safe"

#

There's currently an aliasing bug in .NET with regard to Unsafe.As<T>, but it's not a problem in Unity and the aliasing bug will (hopefully) be fixed soon

urban warren
final steeple
urban warren
#

My other two options are to either say f-it and use straight up reflection, or to say f-it and generate a C# script that is then used at runtime...

final steeple
#

Or rather, you need to subtract sizeof(nuint) * 2

granite viper
#

is it unsafe wrt GC because GC can move the data in between getting the pointer and writing to it

final steeple
#

So 8 on 32-bit, 16 on 64-bit

south ibex
#

Working on a parser for a node graph. Each node can return different values and I need to handle that. Would the vistor pattern be appropriate for this?

I guess the parser will be the visitor and each node handles giving it the correct data.