#archived-code-general

1 messages · Page 408 of 1

tulip spruce
#

and the settingsScript control the settings menu

#

which pops up when I press options

rigid island
#

okay but they do that already no? because its in DDOL scene as singleton

#

your error isnt related to settings though, its because you need a way to assign pauseMenu

tulip spruce
#

then everything works as I intended it to

rigid island
plucky inlet
#

A solution would be, to keep your UI a static thing over all scenes by making it a child of your scripts gameobject.

full canopy
#

can someone explain to me why you aren't allowed to have a prefab reference itself correctly? the easiest workaround is to just have two of the exact same prefab but with the reference pointing to each other, but (1) that's stupid, and (2) I'm now spawning alternating objects using the reference and any changes I make to one prefab I have to remember to bring to the other.

#

its mega annoying and has been a pain to debug for forever all to find out its forcing the reference to be something i didn't put in it in the first place
it broke so many features that i was trying to work around

rigid island
full canopy
#

you don't use prefabs in runtime?

rigid island
#

prefabs are just "templates" to gameobject

full canopy
#

exactly

#

spawn in new objects from prefabs during runtime

#

what else would i do lol

rigid island
#

yeah the one spawned is a gameobject

#

so what do you mean prefab referencing itself

#

you want the spawned object ?

full canopy
#

oh i see the confusion

#

the spawned object needs a reference to its original prefab because the spawned object can spawn another copy of itself (its a lot more complicated then that but to shorten the whole process down thats sufficient lol)

rigid island
#

and object spawning itself sound like a recursion nightmare lol

full canopy
#

its not a recursion nightmare

plucky inlet
#

It sounds like you are trying to force your system into it instead of taking a step back and for example using a static manager that can be fetched from instead of let the object do runtime stuff on its own

full canopy
#

if you want more details-
its a magazine for a gun. its a vr game so there is an ammo pouch, the game checks what items you have picked up last, and associates a prefab from them. picking up a magazine or the gun it goes in associates that magazine prefab with the ammo pouch.

knotty sun
#

Ah, I see the problem, when you spawn from a prefab all of the references are updated from editor instances to runtime instances. So a prefab referencing itself the prefab reference would also be updated to the new gameobject instance

plucky inlet
full canopy
full canopy
knotty sun
plucky inlet
full canopy
#

thx for the tips
still though, why is this a forced feature?

plucky inlet
#

You can still pass in the prefab you are instantiating to the new instantiated object by script with a simple Init() method

knotty sun
#

because the instantiation routine does not know the difference

slate fiber
#

Has anyone ever worked with easy save 3 and webgl? I cant seem to make Easy save work on webgl games

knotty sun
copper rose
#

Hi there, i have some trouble trying to get working my game smoothly, its first time i do it, so im searching in documentation and some threads in unity forum and this is what i got, it works but in unity editor works smooth with moouse or gamepad, but not in real device with my gamepad , there is my input manager and my cam controller

thin aurora
tawny elkBOT
thin aurora
#

Namely the fact methods like LateUpdate are unknown, and in general syntax highlighting is very off

#

Please configure it first, then we can help you

copper rose
vestal arch
copper rose
#

i got installed visual code with the common but still looking like this

copper rose
thin aurora
vestal arch
thin aurora
thin aurora
#

That it, depending on a few prerequisites obviously

vestal arch
#

but also visual studio code does work fine in my experience

copper rose
#

for me works fine, then only i have found is lateupdate and other methods from unity are grey

vestal arch
#

if you're familiar with it and can set it up properly then you should just use the one that's more comfortable 🤷

copper rose
#

im comfortable with that

thin aurora
thin aurora
#

These methods should be known Unity methods, but they are not

#

Right now they are listed as being unknown methods which is not correct

#

If you lack the intellisense here, you likely have to manually write each method, do you?

copper rose
#

just disable-enable the extension

thin aurora
#

That looks even worse 😄

#

Now ALL the intellisense and highlighting is gone

#

If you want/can change then you can also try Jetbrains Rider. It has a single plugin you need to install I believe

copper rose
#

ok uninstalled extension and installed again

thin aurora
#

Weird. You have auto completion but it doesn't know LateUpdate is a reserved method name

copper rose
#

i will check later jetbrains, but i want to try to improve this code 🙂

thin aurora
#

Generally I would expect it to work properly but maybe this is just VSC being weird as always

thin aurora
#

Regardless, I suppose this is how it works then

vestal arch
copper rose
#

ok im just installed for now jetrider

#

im earing about that long time ago so maybe is a good moment for testing

thin aurora
#

Jetbrains is skyrocketing when it comes to supporting different c# frameworks

#

Which is both surprising and generally weird considering you'd expect applications like VSC and VS to get the same treatment since they are not from a 3rd party company

copper rose
#

ok, about the code to manage my gamepad, any suggestion? i have to deal also with the bad support on macos with gamepad, my ps4 gamepad works, but some times when it comes to standby i have to re-plug again

plucky inlet
copper rose
copper rose
plucky inlet
#

And your issue is your gamepad movement is not smooth in runtime but in editor?

copper rose
#

yes

plucky inlet
#

Did you ever test another gamepad?

copper rose
#

i only have this one

#

do you think the code is fine right?

plucky inlet
#

I mean, it works in editor, so either macos is trying to do something in "game mode", maybe disable that, or your gamepad is trying to do something ingame mode or is broken entirely, if its having connection issues. macos on latest updates?

copper rose
plucky inlet
#

well... that is some minor information you should put in your introduction of the question 😄

#

How is it connected, BT, wired?

copper rose
grand aurora
#

Hi, gyus. I am trying to bake a light. After baking has been completed, the light on the wall seem to be correct, but after importing a lightmap, everything becomes too bright. Just moved to unity 6 and have never had this problem before. Also, it does not seem that baked light maps are so bright..

#

The problem was that, for some reason, unity marks all lightmaps as default in the scene folder. I changed it to lightmap, dir lightmap and shadowmask accordingly and it fixed the problem. But looks like unity set it as default every time..

#

Why unity marks lightmaps as default? it takes some time to correct it...

copper rose
#

you add the scene as additive?

late lion
copper rose
plucky inlet
plucky inlet
wheat spruce
#
private void Update()
{
  _speed += (_moveDirection != Vector2.zero ? 1 : -1) * _speedRate * Time.deltaTime;
  _speed = Mathf.Clamp(_speed, 0f, _maxSpeed);
}

private void FixedUpdate()
{
  Vector2 move = _moveDirection * _speed * Time.deltaTime;
  _rb.AddForce(move, ForceMode2D.Force);
}```Does this seem like a decent way to implement a simple vehicle controller? It's a little stiff which is mostly because the code hasnt been fine tuned yet
leaden ice
#

(the one in FixedUpdate)

#

Also all of it should really go in FixedUpdate

cyan ivy
heady iris
#

Time.deltaTime is set to Time.fixedDeltaTime within FixedUpdate

#

It would still be incorrect to factor in the length of the frame or the length of the physics update when using AddForce, either way

wheat spruce
#
private void FixedUpdate()
{
  _speed += (_moveDirection != Vector2.zero ? 1 : -1) * _speedRate * Time.fixedDeltaTime;
  _speed = Mathf.Clamp(_speed, 0f, _maxSpeed);

  Vector2 move = _moveDirection * _speed;
  _rb.AddForce(move, ForceMode2D.Force);
}```This definitely feels much smoother
heady iris
#

That looks correct.

wheat spruce
#

plus move doesnt end up being really small

heady iris
#

You accelerate towards a target velocity, moving by Time.fixedDeltaTime * _speedRate each physics update

#

Well, it's not really a speed, but close enough

#

you accelerate towards a target force value

#

you'll wind up getting a sort of "double-smoothing" effect from this -- you accelerate towards a force value, and that force value causes you to accelerate!

#

You might compare this to just doing _rb.velocity = move; and seeing how that feels

wheat spruce
#

Yeah, the _speed property is mostly so I can control the initial acceleration. But it does seem counter-intuitive considering the rigidbody does the same thing

leaden ice
wintry crescent
#

Is there a many-to-many dictionary?

#

because I can only have 1 instance of a key

#

actually no, I'll just use a list as the value

vestal arch
#

dict to set/list of value

magic harness
#

Hello guys. Im having a bit of a gigantic trouble with loading some data from Json.

My current project has a single entry point for Data, which is the Profile class. We load a Json file containing an object of type Profile at startup and then save it on application quit.

Profile has a list of characters, characters have an inventory, inventory has inventory entries and inventory entries have and item.

Item is polymorphic so it can be an Equipment.

Equipments have two lists, one for PrimaryAttributeModifiers and a Second one for SecondaryAttributeModifiers.

An Equipment is created whenever the player collect loot from the ground(example) and it calls the Equipment constructor which accepts an EquipmentSO.

This far, everything works great. It serializes the data correctly and by debugging the load call on the Json, also reads everything correctly. All the lists work in exception of the attribute modifiers.

I've tried a plethora of solutions but it seems to not be able to deserialize the attribute modifier list by any means at all.

Things i've tried:
-Simpliying attribute modifer inheritance to not include vector 2(newtonsoft doesnt like the normalize properties)
-Changing serialization and deserialization settings
-Removing the Unity's SerializeField properties and just using JsonProperty instead.
-Adding parameterless constructors with the JsonConstructor attribute.
-Saving and loading the items while equipped (changing the list type)

heady iris
#

for the first point, you can add converters that correctly handle things like Vector2

#

you'll need to show us how an attribute modifier is defined and how you're storing them

magic harness
#

Ok.


namespace Attributes
{

    [Serializable]
    public abstract class AttributeModifier
    {
        [JsonIgnore] public Action OnValueChanged;


        [field: SerializeField, JsonProperty] public bool isPercentage { get; set; }
        [field: SerializeField, JsonProperty] public float timeActive { get; private set; }
        [field: SerializeField, JsonProperty] public int minRoll { get; private set; }
        [field: SerializeField, JsonProperty] public int maxRoll { get; private set; }
        [field: SerializeField, JsonProperty] public bool isRolled { get; private set; }
        [field: SerializeField, JsonProperty] public float value { get; private set; }
        [JsonIgnore]
        public float Value
        {
            get
            {
                if (!isRolled) return RollModifier();
                return value;
            }
        }


        [JsonConstructor]
        public AttributeModifier() { }

        public AttributeModifier(int minRoll, int maxRoll, bool isPercentage = false, float timeActive = 0)
        {
            this.minRoll = minRoll;
            this.maxRoll = maxRoll;
            this.isRolled = false;
            this.timeActive = timeActive;
            this.isPercentage = isPercentage;
        }


namespace Attributes
{
    [Serializable]
    public class PrimaryAttributeModifier : AttributeModifier
    {
        [field: SerializeField, JsonProperty] public PrimaryAttributes stat { get; set; }


        [JsonConstructor]
        public PrimaryAttributeModifier() : base() { }

        public PrimaryAttributeModifier(PrimaryAttributes stat, int minRoll, int maxRoll, bool isPercentage) : base(minRoll, maxRoll, isPercentage)
        {
            this.stat = stat;
        }
    }
}

#

CLASS EQUIPMENT CONSTRUCTOR

public Equipment(EquipmentSO preset) : base(preset)
    {
        Debug.Log(this);
        enchantItems = new();
        upgradeLevel = 0;
        primaryModifiers = new();
        secondaryModifiers = new();
        this.slot = preset.slot;
        this.enchantSlots = preset.enchantSlots;
        foreach (PrimaryAttributeModifier modifier in preset.primaryModifiers)
        {
            PrimaryAttributeModifier newMod = new PrimaryAttributeModifier(modifier.stat, modifier.minRoll, modifier.maxRoll, modifier.isPercentage);
            newMod.RollModifier();
            primaryModifiers.Add(newMod);

        }
        foreach (SecondaryAttributeModifier modifier in preset.secondaryModifiers)
        {
            SecondaryAttributeModifier newMod = new SecondaryAttributeModifier(modifier.stat, modifier.minRoll, modifier.maxRoll, modifier.isPercentage);
            newMod.RollModifier();
            secondaryModifiers.Add(newMod);

        }
    }

and its stored here

#

also just tried sving the equipment while it is equipped, so the list is List<Equipment> instead of List<item> and the same result, so. yeah

wintry crescent
magic harness
#

The equipment class doesnt get deserialized properly. The Serialized Json data is totally fine.

The only things missing are the modifiers

#

doesnt matter what happens, the list storing the modifiers gets set to empty

wintry crescent
magic harness
#

they do. If i kill a mob, loot the item everything is fine

#

After i close the game and check the serialized data

#

everything is fine

#

when i open the game and debug.log the data that i will deserialize, everything is fine

#

when rebuilding the Equipment, lists are empty

wintry crescent
#

EquipmentSO is your serialized data and you make your equipment from it

#

so those foreach loops, in that constructor, do they run?

magic harness
#

no. i have a default parameterless constructor in the same class.

No EquipmentSO is a scriptable object that i use to create normal instances of equipments(since i want to have randomized stats per drop)

#
    [JsonConstructor]
    public Equipment() : base()
    {
    }
#

this is what gets called for deserializing

#

My Json settings are as follows:
Serializing
TypeNameHandling = TypeNameHandling.All,
ObjectCreationHandling = ObjectCreationHandling.Replace,
DefaultValueHandling = DefaultValueHandling.Ignore,
Formatting = Formatting.Indented,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,

Deserializing:

#

TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
DefaultValueHandling = DefaultValueHandling.Ignore,
PreserveReferencesHandling = PreserveReferencesHandling.Objects

eager tundra
#

don't you want to use the other constructor with the actual parameters? this way you're telling the deserializer to simply create a new instance with default values

magic harness
#

but i am using ObjectCreatingHandling.Replace and PreserReferencesHandling.Objects.

It works fine with all the other data that i'm saving and loading

#

not sure how i can pass a scriptable object parameter to the actual deserializing construtor tbh

wintry crescent
leaden ice
#

Auto is basically an optimization where the type name isn't included when it's not ambiguous.

wintry crescent
magic harness
#

ive almost done all possible combinations of serializer settings in there

#

Yeah i've just removed all parameterless constructors from equipment, item and attribute modifiers

eager tundra
#

where exactly is deserialization happening?

magic harness
#
  public Profile LoadProfile(string name)
        {
            string fileLocation = GetPathToFile(name);
            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto,
                ObjectCreationHandling = ObjectCreationHandling.Replace,
                DefaultValueHandling = DefaultValueHandling.Ignore,
                PreserveReferencesHandling = PreserveReferencesHandling.Objects
            };

            if (!File.Exists(fileLocation))
            {
                throw new ArgumentException($"No persisted GameData with name '{name}'");
            }
            Debug.Log(JsonConvert.DeserializeObject<Profile>(File.ReadAllText(fileLocation), settings));
            Debug.Log(File.ReadAllText(fileLocation));
            var profile = JsonConvert.DeserializeObject<Profile>(File.ReadAllText(fileLocation), settings);
        
            return JsonConvert.DeserializeObject<Profile>(File.ReadAllText(fileLocation), settings);
        }

magic harness
tiny delta
#

Howdy folks, quick question. Is it possible to change a setting or something to make it so FixedUpdate waits for Start before running? Maybe I am confused or something but it seems like it oftentimes a frame of FixedUpdate will occur before Start.

wintry crescent
tiny delta
#

I did consider that, but it depends on a reference to another script which gets some stuff during Awake, so it would mess everything up

#

Currently I just have a variable called "started" which is set to true once Start runs, but it feels like bad practice to do

heady iris
#

Start runs before the first Update call

#

There aren't any other guarantees

obsidian mulch
#

It should run awake on all objects before any fixedupdate calls afaik

heady iris
#

Awake will run as soon as the object comes into existence, yeah

wintry crescent
heady iris
#

(as long as the game object is activated)

obsidian mulch
#

There’s also lateupdate, but not sure if there’s latefixedupdate?

wintry crescent
wintry crescent
obsidian mulch
#

But you could probably also run if (whatever != null) in an update to make sure

wintry crescent
wintry crescent
#

very weird that fixedupdate can run before start, that's funny

#

can it run before onenable? that could be a good idea as well

heady iris
heady iris
obsidian mulch
#

How can it run at the same time?

wintry crescent
heady iris
obsidian mulch
#

I get that it will run both on the same frame, but I’m pretty sure it will create and call references in Awake before it makes it to OnEnable

heady iris
#

not literally simultaneously

#

Awake and OnEnable execute together as a pair if the behaviour is enabled upon creation

wintry crescent
#

so
obj1.Awake
obj2.Awake
obj3.Awake
obj1.OnEnable
obj1.Start
obj2.OnEnable
obj2.Start
obj3.OnEnable
obj3.Start

#

that's how I remember it

heady iris
wintry crescent
#

it was a while since I last checked it

magic harness
#
    public SecondaryAttributeModifier[] secondaryModifiers { get; private set } = new SecondaryAttributeModifier[10];

Json serializes correctly

but same thing, it deserializes the array with 10 null values

wintry crescent
wintry crescent
tiny delta
#

Just checked, the reason awake has been causing problems is because there's info given to that other script when it's spawned in, and so running Awake actually runs before that information is given sometimes

obsidian mulch
magic harness
leaden ice
wintry crescent
heady iris
#

Awake is too fast. Start is too slow.

wintry crescent
heady iris
#

I'll often create an "Init" method that I manually call after doing some setup

magic harness
tiny delta
#

Yup, I've improved it a lot now by getting rid of like 90% of the stuff in my dumb CharacterInfo scriptable object

wintry crescent
tiny delta
#

It just has the stuff for input actions and starting positions

wintry crescent
tiny delta
#

So maybe what I'll look at doing is moving the Start code to Awake, and then setting the starting position of that object in the other script

#

And I'm getting closer and closer to being able to get rid of the scriptableObject entirely

magic harness
magic harness
#

thats my entire json file, as i said, im using a single entry point

#

inside it there are many objects being serialized correctly

#

including lists and polymorphic types

wintry crescent
magic harness
#

because thats one that has been loaded already and then saved again

#

let me send you another one then

#

check id 125 at line 660

placid summit
#

Hi I did not know this but the Mesh API with RecalculateNormals() has UV seam issues: Imported Meshes sometimes don't share all vertices. For example, a vertex at a UV seam is split into two vertices, so the RecalculateNormals function creates normals that are NOT SMOOTH at the UV seam!

#

I can understand from a speed perspective but they ought to offer a slower version that fixes this

heady iris
#

I know that using the "Mikktspace" option for calculating tangent vectors can cause meshes to be split along UV seams

#

(since it uses the UV map to figure out the tangent)

#

However, the resulting vertices should have identical normal vectors

placid summit
#

known normal calculation issue

heady iris
#

Oh right, duh. It has to split across uv islands

foggy pasture
#

heya, I was hoping someone could help me out a bit with an issue I'm out of my depth on. I have a cinemachine camera (unrelated to this issue) that's tracking a target, and I have a pixel perfect component on said camera (my own, I ripped out the pixel position rounding component from the 2d one). as you can see in the video, when moving horizontally there's zero jitter, perfect. but when moving in the z axis, there's quite a bit of jitter, even though the code should be rounding it the same

    public Vector3 RoundToPixel(Vector3 position) {
        float unitsPerPixel = 1.0f / pixelsPerUnit;
        if (unitsPerPixel == 0.0f)
            return position;

        Vector3 result;
        result.x = Mathf.Round(position.x / unitsPerPixel) * unitsPerPixel;
        result.y = Mathf.Round(position.y / unitsPerPixel) * unitsPerPixel;
        result.z = Mathf.Round(position.z / unitsPerPixel) * unitsPerPixel;

        return result;
    }

    // Snap camera position to pixels using Camera.worldToCameraMatrix.
    void PixelSnap() {
        Vector3 cameraPosition = m_Camera.transform.position;
        Vector3 roundedCameraPosition = RoundToPixel(cameraPosition);
        Vector3 offset = roundedCameraPosition - cameraPosition;
        offset.z = -offset.z;

        // Get world to local camera matrix without scale
        var invPos = Matrix4x4.TRS(cameraPosition + offset, Quaternion.identity, Vector3.one).inverse;
        var invRot = Matrix4x4.Rotate(m_Camera.transform.rotation).inverse;
        var scaleMatrix = Matrix4x4.Scale(new Vector3(1.0f, 1.0f, -1.0f));

        // Calculate inverse TRS
        m_Camera.worldToCameraMatrix = scaleMatrix * invRot * invPos;
    }
#

i was hoping someone here might be able to provide insight into what i'm doing wrong here

#

a thought I've had is that since my outlines are depth and viewnormal based, it might be because the depth values are changing? I'm not sure

low harbor
#

Hi, is there a way so the input to result is such:
0 = (0,0,1)
1 = (1,0,0)
2 = (0,0,-1)
3= (-1,0,0)
Or, return in Vector3Int.forward, right, down, left ?
With sine ? Or...?

heady iris
foggy pasture
#

it is, at a 30* tilt, which would make sense... adding a pan angle introduces x jitter

rigid island
heady iris
#

I bet you need throw in a sin(30deg) or cos(30deg) factor somewhere

knotty sun
foggy pasture
#

yeah I agree, let me mess around with that and I'll try and see, thanks

heady iris
#

I am working on a tool that needs to be able to run a set of "Filters". Some filters require no context at all (e.g. a filter that randomly says "yes" or "no"). Others require context (e.g. a position in the world).

I'm having some trouble figuring out how I'll structure this.

An existing implementation of mine has several abstract classes, such as:

public abstract class Filter {
  public abstract bool Test();
}

public abstract class PositionFilter {
  public abstract bool Test(Vector3 pos);
}

The nuisance here is that I want to be able to put Filters into a List<PositionFilter>. After all, Filter's Test method needs strictly less information than PositionFilter's Test method.

The current fix is to create classes that just hold an instance of a simpler filter:

public abstract class PositionBaseFilter {
  [SerializeField] private Filter filter;

  public bool Test(Vector3 pos) => filter.Test();
}

This works, but I'm wondering if I can do something to avoid all these "holder" classes.

Ideally, each class will ask for a specific set of information, and I'll be allowed to plug in any class that doesn't require information that my code can't provide.

#

I'm not sure if I can actually do this with C#'s type system.

#

the dream scenario would result in something like this:

  • RandomFilter <-- no requirements, can fit anywhere
  • PositionFilter <-- fits anywhere that can provide a "position" input
  • PositionAndRotationFilter <-- fits anywhere that can provide both a "position" input and a "rotation" input
plucky inlet
#

Why not have a main class to inherit from or an interface?

heady iris
#

The nuisance is that this is the opposite of a classic inheritance hierarchy

#

If I made PositionFilter inherit from Filter, it would have this pointless Test method that doesn't work

plucky inlet
#

Why does Filter need the test() then?

heady iris
#

Because Filter represents a filter that can make a decision without any input

plucky inlet
#

So its a DecisionFilter, not a plain filter

heady iris
#

the point is that inheritance makes no sense here -- filters that require more inputs aren't a "subclass" of filters that require fewer inputs

#

You cannot use a PositionFilter like a Filter. It's actually the exact opposite

#

a Filter works anywhere that a PositionFilter does

#

some kind of inverse Liskov substitution principle

#

This also makes interfaces non-useful

plucky inlet
#

So, what do you want to achieve actually? You want to have a list of different types?

heady iris
#

Suppose I have some code that knows a position

#

It wants to make a decision based on that position

#

I want it to be able to run any kind of filter that can operate with only a position input

#

This includes:

  • Filters that require a position
  • Filters that require nothing at all
#

It excludes filters that require any other kind of information

#

You can do the check at runtime, of course, but that's not very satisfying

vestal arch
#

so i have a few disconnected trains of thought floating around

  • this would require something akin to super in java (as in, generic constraints) which c# doesn't seem to have
  • perhaps instead of requiring nothing (Filter) vs requiring Position vs requiring Position&Rotation, you could make it unary?
    • a nullary filter would just ignore the input, perhaps the input could be null
    • a unary filter would just have that input, directly?
    • a binary+ filter would have the inputs as a struct

along that latter train of thought; maybe you could have a unified FilterData type? that doesn't seem too great to work with though, static checking would be hard

#

maybe something via attributes...

heady iris
#

the FilterData idea is roughly what I've done in another place in my game

#

It's kind of gross. I have an interface for each kind of data that adds a property, and I downcast to those types to see if I can give them the information

#

Then, when the class does work, it checks if it got all of its information and throws an exception if that didn't happen

#

Obviously, static type checking goes out the window here

vestal arch
heady iris
#

Contravariance did come to mind

heady iris
#

And that is not the case here.

vestal arch
#

if the parent is generic, perhaps that could work

heady iris
vestal arch
#

but that goes back to the FilterData thing

plucky inlet
#

I am just trying to wrap my head around what combinations you have and how you distinguish your filters as well as how do you applay them. where do you want to filter them out?

heady iris
#

One filter might need to know about foo, bar, and baz to be able to make a decision

#

Another might need just foo

#

And a third might need nothing at all

plucky inlet
#

But shouldnt your filters just get the data available and decide on their own?

heady iris
#

Any context where I can execute the first filter -- meaning I provide it with foo, bar, baz -- is also a context where the second filter and third filter are valid

heady iris
#

But I think that's not possible

vestal arch
#

a given Comparable<T> can make a decision based on T
T can get more specific
in usage, U super T is used, so Comparable<Object> is assignable to Comparable<String> for example

#

what about having interfaces for each input data point?

vestal arch
#

i think you can get static analysis with this though thonk

#

one sec

heady iris
#

It's not "Does it implement X?"

#

it's "Does it ONLY implement X?"

#

Having one interface for each type also implies that you can ask questions based on exactly one piece of information

vestal arch
#

isn't that intended though

heady iris
#

No. If a filter demands foo, bar, and baz, you must give it all three of those to make a decision.

plucky inlet
vestal arch
#

yeah ok i think i misunderstood the perspective

heady iris
#
public interface INeedsPosition {
  public bool Test(Vector3 pos);
}

public interface INeedsRotation {
  public bool Test(Quaternion rot);
}

public class SomeFilter : INeedsPosition, INeedsRotation {
  // ...
}

This doesn't fit my design.

vestal arch
#

ah no that's not what im talking about

heady iris
#

I want this filter to have one method that makes a decision based on a position and a rotation

#

And that just doesn't fit at all, yeah

vestal arch
#

IHasRotation and such, rather

heady iris
#

Yeah, interfaces work the other way

vestal arch
#

i think im explaining my idea poorly, i'll go back to making my example

heady iris
#

This has convinced me that I can't warp the C# type system into doing this 😛

plucky inlet
#

How about custom "tags" to assign and based on that Init the filter and do its local thing?

heady iris
knotty sun
#

Sounds to me like you need a base class to make a variable able to hold multiple class types then use reflection to find which Test method is implemented

plucky inlet
#

I also wonder, do you want to run the filters runtime but prefiltered on editor? or do you want to filter them out in runtime?

heady iris
#

I'm setting these up in the inspector

plucky inlet
#

Ah got it.

heady iris
#

Which does mean I can just filter the list of choices based on, say, attributes

#

That's probably going to be the way forward

plucky inlet
#

So you could just reflect to the methods available and add them to a custom event to call those functions?

heady iris
#

I'm envisioning something like this

plucky inlet
#

Thats what I did to call stuff on scripts from UI and not to have tie up everything. Just select the type in inspector, update the dropdown to add the functinos to call and then just call the singleton of it and fire those methods.

heady iris
#
[Provides(typeof(FooInformation)), SerializeReference] List<Filter> filters;

The inspector would only show me classes that don't require any other kind of information.

Filter would wind up looking like this:

public abstract class Filter {
  public abstract bool Test(FilterData data));
}
#

and FilterData would contain all the possible things you could give to a filter

#

So it would be perfectly legal to run a filter without all of the data that it needs

#

But the inspector would forbid me from assigning such filters in the inspector

tulip spruce
#

How do I fix that Don'tDestroyOnLoad does not keep deavtivated gameobjects?

#

or how do I work around that

latent latch
#

whatcha mean

leaden ice
latent latch
#

I don't remember that behaviour

leaden ice
#

that's not a thing

plucky inlet
latent latch
#

Oh I think what you may mean is that because the object is deactived it may not be flagging DDOL

tulip spruce
heady iris
leaden ice
#

Show your code and what's happening exactly

heady iris
#

I would throw out any types that need information I'm not giving

tulip spruce
#

😄

latent latch
#

is the object ever calling start^

leaden ice
#

so DDOL is not the problem

tulip spruce
plucky inlet
tulip spruce
#

should it be in Awake?

leaden ice
#

The problem is trying to run code on a script that isn't active

tulip spruce
leaden ice
#

put the code on an active object is the solution

tulip spruce
#

I did not think about that

#

big brain

#

thanks

#

I am still learning

leaden ice
#

All of us are

vestal arch
leaden ice
plucky inlet
#

It all started from there 😄

heady iris
#

I want to be able to plug less-specific filters into places that support more-specific filters

#

If I can provide ABC, then filters that need ABC, or AB, or C, or nothing at all should all fit

#

But filters that need D shouldn't fit

leaden ice
#

Are static/compile time errors a requirement here?

#

Or would runtime errors be ok

heady iris
#

I'd prefer the former. I can already achieve this (with some headaches) if I just check at runtime

leaden ice
#

So what's the typical use case look like?

Something like... uh...

myThing.Filter(new FilterA());```?
vestal arch
#

(i am still trying btw. i think i broke the java playground...)

leaden ice
#

Where myThing is of some specific type that should accept certain filters and not others?

heady iris
#

The typical form is something like this

#

wait, typing code on my ipad sucks

#

it sends the message early like 50% of the time

#

Suppose I'm spawning prefabs along a line

#

I want to be able to reject certain placements based on the chosen position

leaden ice
#

This could probably be done with a Roslyn Analyzer btw

heady iris
#

But I should also be able to reject placements based on nothing at all (e.g. a coinflip)

leaden ice
#

which lets you add new rules to the compiler basically

heady iris
#

also, this particular thing is editor-only -- but I've run into identical problems in runtime code

#

But in both cases, I'm setting everything up in the inspector in advance

#

so I can get away with a custom editor that enforces the rules

plucky inlet
#

Could you explain a bit more, how you add those filters. or rather, to what? its in inspector, right? so you have some kind of serialised list in inspector and you want to give the list some kind of property, so it knows what iflters to accept?

leaden ice
#

I'm not even sure "type information" is enough to work with.

#

Knowing the filters operates on a Vector3, for example, doesn't mean the filter works on any Vector3

#

it might take only positions

#

or euler angle rotations or something

plucky inlet
heady iris
vestal arch
#

wait i might have a system going in java...

heady iris
#
[Serializable]
public abstract class Scorer : IPolymorphic
{
    public abstract float GetRawScore();
}

[Serializable]
public abstract class EntityScorer : IPolymorphic
{
    public abstract float GetRawScore(Entity entity);
}

[Serializable]
public class EntityConstantScorer : EntityScorer
{
    [SerializeReference] private Scorer scorer;

    public override float GetRawScore(Entity entity)
    {
        return scorer.GetRawScore();
    }
}

Here's an example of what I've done before.

#

I'll store a List<EntityScorer> on something that needs to compute a score based on an entity

#

Rather than also having a List<Scorer>, I created EntityConstantScorer

#

That lets me fit a Scorer into a list of EntityScorer (through a wrapper)

plucky inlet
#

phew, that feels hacky 😄

tulip spruce
# leaden ice put the code on an active object is the solution

I did another approach, because I had issues referencing the gameobject in the other gameobject, so what I did was have the other gameobject active but the canvas turned off. then the code will run so DDOL will run and then I enable the canvas back and deactivate the gameovject. and it worked. I am doing a lot wrong. ik

leaden ice
tulip spruce
#

thanks for the help anyway

#

I would be helpelss else

heady iris
#

and they don't overlap much in what information they get

#

The punchline might be that this problem doesn't exist at all 😉

#

i.e. instead of having filters like:

  • ABD
  • BD
  • ABCD

I just have:

  • ABC
  • AB
  • A
plucky inlet
#

I think we all knew almost form the start of this conversation, but eager to get the perfect solution 😄

heady iris
#

with very little crosstalk

#

Yeah :p

#

I've banged into this several times and dealt with it in varying ways

#

It was very helpful to talk about it! Thanks!

plucky inlet
#

Oh, thank you too. Very challenging and was fun to think about that whole structuring , great insightful conversation 🙂

heady iris
#

If I do run into a situation where I have lots and lots of overlap, I'll just do a runtime check

plucky inlet
#

If you have ABC, AB, A, you could even just use an enum. But as soon as you have a mixture of those, it wont work

still jungle
#

u can use enum bitmask to combine

plucky inlet
#

I just use enum to control roles for example. the higher the enum value, the higher the role and less things are restricted or what not

heady iris
#

This does remind me of "blackboards" in the context of game AI

#

where you have a shared pool of information and you can't really be sure what will be in it

vestal arch
#

!code

tawny elkBOT
vestal arch
#

can't construct multiple-datapoint-filters with this, T & U can't be used as a type like that, unfortunately...

heady iris
#

I bet Typescript can do some bullshit here

#

(as it always can)

vestal arch
#

of course it can lmao

#

as everywhere 👍

#

(maybe i'll try that... (like actually))

limpid siren
#

hello, I'm using this code to force a 4:3 aspect ratio on the game I'm working on
it works well on a 1920x1080 laptop screen, but I got a friend to try the game on steam deck, and the aspect ratio change did not work. The game just filled the screen.
Any idea how I could fix this?

leaden ice
# heady iris i.e. instead of having filters like: - ABD - BD - ABCD I just have: - ABC - A...

How about just something like...:

public class Context {
  public Vector3 position;
  public Entity entity;
  public Color color;
}

public abstract class AbstractFilter {
  public abstract bool Filter(Context ctx);
}

public class PositionFilter : AbstractFilter {
  public override bool Filter(Context ctx) {
    return ctx.position.x > 5;
  }
}```
And just let the filters optionally take whatever data they want from the Context object
vestal arch
#

typescript is just 2 programming languages on top of each other with one masquerading as a type system

tulip spruce
#

is it possible to change something in the inspector when the game is running and have those changes be persistent?

vestal arch
heady iris
plucky inlet
heady iris
#

That's what I'll do if I just need one component

wheat spruce
#
private void AddMovementForce()
{
  Vector2 movementForce = _moveDirection * _speed;

  float angle = Vector3.Angle(transform.up, _wheels.TurnDirection);
  Quaternion rotation = Quaternion.Euler(0, 0, -angle); // take the

  Vector2 finalDirection = rotation * movementForce;
  _rb.AddForce(finalDirection, ForceMode2D.Force);
}```I'm trying to make it so that the direction the object at the front travels becomes influenced by the direction that the back object is facing. I've tried a few different things, and nothing seems to do the right thing
#

Something more like this

#

_moveDirection is the way the user aims the front half of the train, but its the back wheels that need to influence some steering

vestal arch
#

@heady iris in ts it Just Works™️ lmao
playground

plucky inlet
#

yeh, typescript, python, just throw in whatever you want and get whatever you want 😄

heady iris
#

Vector3.Angle is not signed

#

So you can't tell left from right

vestal arch
heady iris
#

Consider using Quaternion.FromToRotation

#

This gives you a rotation from one direction to another

#

That might misbehave for an exact 180 degree mismatch, though

#

In that case, Vector3.SignedAngle would be more reliable. It needs a third direction as a reference point

#
Vector3.SignedAngle(one, two, Vector3.forward);

This would be appropriate.

#

SignedAngle gives you a number in the [-180..180] range. I can never remember which way is negative

wheat spruce
#

float angle = Vector3.SignedAngle(_moveDirection, _wheels.TurnDirection, Vector3.up); Are these the right properties to use in it? I've tried a number of combinations and none seem correct

heady iris
#

You need forward, not up

#

The third argument is the axis that you're rotating around

wheat spruce
#

ooooohh right

heady iris
#

in a 2D game, forward points into the screen

#

You might want to calculate two signed angles relative to some arbitrary reference point

#
float moveAngle = Vector3.SignedAngle(_moveDirection, Vector3.right, Vector3.forward);
float wheelsAngle = Vector3.SignedAngle(_wheels.TurnDirection, Vector3.right, Vector3.forward);

float skewedAngle = Mathf.LerpAngle(moveAngle, wheelsAngle, 0.5f);

Vector3 resultDirection = Quaternion.AngleAxis(skewedAngle, Vector3.forward);
#

I think that'll do it.

#

Note that it'd be dramatically simpler to just do

#
Vector3.Slerp(_moveDirection, _wheels.TurnDirection, 0.5f);
#

I just don't know what's going to happen if those two vectors are antiparallel

#

(i.e. exactly 180 degrees apart)

wheat spruce
# heady iris ```cs float moveAngle = Vector3.SignedAngle(_moveDirection, Vector3.right, Vecto...
    float moveAngle = Vector3.SignedAngle(_moveDirection, Vector3.right, Vector3.forward);
    float wheelsAngle = Vector3.SignedAngle(_wheels.TurnDirection, Vector3.right, Vector3.forward);
    float skewedAngle = Mathf.LerpAngle(moveAngle, wheelsAngle, 0.5f);

    Quaternion angleAxis = Quaternion.AngleAxis(skewedAngle, Vector3.forward);
    Vector2 finalDirection = (Vector2)(angleAxis * Vector3.up);```I wasnt able to use the Quaternion how it is at the end, is this right?
heady iris
#

You'd want to multiply with Vector3.right at the end

#

since that was your reference point

tulip spruce
#

if I have an event trigger to play an audio on PointerClick, and a OnClick Playgame (it is changing the scene) will the audio not play then?

plucky inlet
wheat spruce
tulip spruce
plucky inlet
heady iris
tulip spruce
tulip spruce
heady iris
tulip spruce
#

ah I see

#

you are good at this

heady iris
#

i can't tell what the issue is

wheat spruce
#

I'm not pressing anything, it just propels to the right

#

are you sure vector.up isnt correct? It would be (0,1,0) and its the Y axis that the front of the train heads towards

heady iris
#

Vector3.forward is a world-space direction here. It's an axis pointing into the screen

#

you're finding the angle between your vehicle's move direction and a reference point

#

(which is Vector3.right)

#

that angle is measured around the forward vector

heady iris
#

all this is doing is finding a direction that's halfway between _moveDirection and _wheels.TurnDirection

#

if _moveDirection is zero it could get a bit weird

wheat spruce
#
    Vector2 movementForce = _moveDirection * _speed;
    Vector3 finalDirection = Vector3.Slerp(movementForce, _wheels.TurnDirection * new Vector2(-1, 0), 0.5f);
    _rb.AddForce(finalDirection, ForceMode2D.Force);```Quick thing to note, I did give the lerp a try. It sort of works, but at the start of the video I try and press A and D to turn the front and it doesnt move
#

it only turns when the back gets tilted

heady iris
#

what's with the scaling on TurnDirection?

wheat spruce
#

to invert the direction

heady iris
#

that's throwing out the Y component entirely

wheat spruce
#

yeah

still jungle
wheat spruce
#

I'll work on it more tomorrow, its past 8pm so I'm going to stop working for the evening

#

will give me time to reflect on the code, I think in general the steering part of the code doesnt do quite the right thing

#

(also havent eaten anything today so I'm probably running on empty 😅)

plain moon
#

Why without animation my character is under root object with colliders? Child object(model) have (0,0,0) coords its not offset or smth else. Just weird thing

leaden ice
#

Then you can see the actual positions of the objects when you select them

#

It will probably show you that the center of the model is offset

#

this is a problem in the 3D model itself

#

You would fix it in Blender (or any other 3D modeling software)

plain moon
#

Set by pivot and this happened 🙂 Download model from mixamo

tulip spruce
#

if I spam onenter sound many times all sound in the scene is gradually being muted and then if I stop it gradually comes back, is that supposed to be like that?

leaden ice
#

See how the collider is super offset from the model?

#

You should adjust the Center of your collider so the pivot is starting from the bottom like the model

plain moon
#

Yes, but can I fix this somehow without blender and etc. I would like to use Root Motion anims. Would it be compatible with pivot in center of model?

leaden ice
#

Add an empty parent and offset the model

#

but if one of the animations is completely offset from the others there's not much you can do about that

#

It's generally much better IMO to have the object's pivot on the ground rather than the center - makes code much simpler.

plain moon
#

That's how it works now. Root is rigidbody and colliders, first child animators and etc

leaden ice
#

you can also just offset the visuals separately

#

you can do whatever you'd like inside that hierarchy more or less

tulip spruce
#

It seems like when I have the exit to menu button (works by onClick: SceneManger.LoadScene(buildnumber_toMainMenu)) But when I do this the music starts to play again

#

music that I have in main menu

#

what would be the best apporach to fix this

leaden ice
#

Shouldn't the main menu music play when you start the main menu?

tulip spruce
#

yes but since I put DDOL on the music

#

oh

#

nvm

#

I need to put another music in the game instead which is not DDOL

leaden ice
#

the pattern is a "DDOL singleton"

#

If you want to simply have one in each scene, you wouldn't use DDOL at all

tulip spruce
#

I don't do DDOL if I not have too

heady iris
#

it's a bit like this

#
public class SimplexNoiseFilter : Filter
{
    [SerializeField, SerializeReference, SerializeReferenceDropdown]
    private PositionSource positionSource;

    // ... more stuff
 }
#

PositionSource is another abstract class that tells you how to get a position

#

One position source just grabs the "position" member from a FilterData object that gets thrown into the filter's Test method

#

Another gets a position from a TransformSource!

#

...one kind of which, in turn, can look to see if you provided a "root" member in the FilterData

#

this also leads to a hilarious function signature

#

public abstract bool TryTest(FilterData data, out bool result);

heady iris
#

and more layers of indirection than a main-story fetch quest

tame summit
#

Hey, I'm not sure where to ask this but im trying to make a car with the wheel colliders and it has low acceleration but fast top speed and im looking to make it a little more realistic

#

I know very little about wheel colliders but I would love to learn more about it

dusk apex
keen turret
#

Hey, I'm trying to get my simulation from c# to a compute shader, it's an implementation of an XPBD solver, distance constraint of the edges and volume constraint of the tetrahedrons, but it looks bad and jitters. Even ensuring no parallel execution so there's no race condition with the numthreads set to 1 (I don't know if this really ensures that it doesn't run in parallel, because it's the first time i write a compute shader in my life). I also tried to compute the rest length and rest volume of the constraints in the gpu to make sure it's not caused due to a difference in floating point accuracy between the cpu and gpu, nothing works, the simulation is not totally broken, it's jittery, This is an example of the distance constraint in c# and on the compute shader:

public void Solve(NativeArray<Particle> particles, float deltaTime)
{
    float alpha = compliance / (deltaTime * deltaTime);

    Particle pA = particles[indexA];
    Particle pB = particles[indexB];
    float w0 = pA.InverseMass;
    float w1 = pB.InverseMass;
    float w = w0 + w1;
    if (w == 0f)
        return;

    Vector3 grad = pA.Position - pB.Position;
    float len = grad.magnitude;
    if (len == 0f)
        return;

    grad = grad / len;
    float C = len - restLength;
    float s = -C / (w + alpha);
    pA.Position += s * w0 * grad;
    pB.Position += -s * w1 * grad;
    particles[indexA] = pA;
    particles[indexB] = pB;
}
#

the compute shader:

[numthreads(1, 1, 1)]
void SolveDistances(uint3 dispatchThreadID : SV_DispatchThreadID)
{
    DistanceConstraint constraint = distanceConstraints[dispatchThreadID.x];
    
    Particle pA = particles[constraint.indexA];
    Particle pB = particles[constraint.indexB];
    
    float w0 = pA.InverseMass;
    float w1 = pB.InverseMass;
    float w = w0 + w1;
    if (w == 0.0f)
        return;

    float3 grad = pA.Position - pB.Position;
    float len = length(grad);
    if (len == 0.0f)
        return;

    float3 norm = grad / len;

    float C = len - constraint.restLength;
    
    float alpha = constraint.compliance / (deltaTime * deltaTime);
    float s = -C / (w + alpha);

    pA.Position += s * w0 * norm;
    pB.Position += -s * w1 * norm;
    
    particles[constraint.indexA] = pA;
    particles[constraint.indexB] = pB;
}
keen turret
cosmic rain
keen turret
pine condor
#

Does anyone know how to spawn a player prefab like with DefaultPlayerPrefab at runtime in unity transport unity 6?

pine condor
leaden ice
pine condor
#

whatever defaultplayerprefab uses idk

leaden ice
pine condor
#

it's asking for a client id

leaden ice
#

Player objects get spawned in as soon as the client connects

leaden ice
#

What are you trying to accomplish here?

pine condor
#

To manually spawn an object as PlayerObject, use the following method:

GetComponent<NetworkObject>().SpawnAsPlayerObject(clientId);

leaden ice
#

Just use your own client id (assuming this is from the client)

pine condor
#

where do i find that?

desert blade
#

How does one get around UnityWebRequest.PostWwwForm(url, JsonUtility.ToJson(payload)) spitting out ascii on the receiving end? Server keeps coming back to me with %7b which is ascii for {

WWWForm() doesn't work though cause that needs to be paired with a content header of x-www-url-encoded .

I find it weird that unity's default post is a x-www-url-encoded but their service api docs only accepts application/json

leaden ice
#

Also what are you trying to do exactly?

desert blade
# leaden ice Also what are you trying to do exactly?

requesting allocations with multiplay requires me to use the TokenExchange API with a payload of projectID and environmentID.

created a class ExchangePayload with the previously mentioned requirements as variables. plugged it into a JsonUtility.ToJson() and slapped that as the form for the UnityWebRequest.Post(url, payload)

Debugging the JsonUtility.ToJson() showed me that it was converting the class to json just fine. Sent it over to the server only to get back a unable to parse body. %7b... is not a valid json

leaden ice
#

Are you sure the server is expecting form data?

#

It's weird that you would be using both HTTP Form data AND json 🤔

#

does this API have documentation?

desert blade
desert blade
#

unless i've butchered this somehow

leaden ice
rigid island
#

just make regular UnityWebRequest Post with that payload

desert blade
#

hmm its screaming at me because of the obsolete function

leaden ice
#

SOmething like this should do

rigid island
#

www class is

desert blade
leaden ice
desert blade
#

wOt

leaden ice
#

try like in the link I shared

rigid island
#

you have to set the headers like the link ^

#

its 3 args

desert blade
#

thanks a lot guys for helping out @leaden ice @rigid island

azure frost
#

My bro and I are having trouble with the Kinematic Character Controller again.

#
if(InputMod.GetButtonDown(CrouchInput)) {
                characterInputs.Crouch = (!characterInputs.Crouch);
                Debug.LogError("We press crouch and are now " + (characterInputs.Crouch ? "crouching" : "standing"));
            }```


```C#
// Crouching input
                        if (inputs.Crouch)
                        {
                            Debug.LogError("Be crouching");
                            _shouldBeCrouching = true;

                            if (!_isCrouching)
                            {
                                _isCrouching = true;
                                Motor.SetCapsuleDimensions(0.5f, CrouchedCapsuleHeight, CrouchedCapsuleHeight * 0.5f);
                                MeshRoot.localScale = new Vector3(1f, 0.5f, 1f);
                                
                            }
                        }
                        else if (!inputs.Crouch)
                        {
                            Debug.LogError("All rise");
                            _shouldBeCrouching = false;

                        }```
Segments taken from two scripts, and we're trying to make a "toggle crouch". What keeps setting "_shouldBeCrouching" to false, causing the character to only remain crouched for one frame?
latent latch
#
if (inputs.Crouch)
{
    Debug.LogError("Be crouching");
    _shouldBeCrouching = true;

    if (!_isCrouching)
    {
        _isCrouching = true;
        Motor.SetCapsuleDimensions(0.5f, CrouchedCapsuleHeight, CrouchedCapsuleHeight * 0.5f);
        MeshRoot.localScale = new Vector3(1f, 0.5f, 1f);
        
    }
}```
Why wouldnt you be crouching if input.Crouch here is to be true? Feels like you've one too many flags going on
azure frost
#

@arctic sparrow

arctic sparrow
#
public void SetInputs(ref PlayerCharacterInputs inputs)

Here's the problem. I have never used ref in any of my code, but I can only theorize that it's responsible for resetting the crouch bool

azure frost
latent latch
arctic sparrow
#

It is indeed a struct.

latent latch
#

As for the code in general, it would probably be more helpful if it was posted via paste site cause I can't figure the flow of it with what's there.

#

May want to look into a statemachine and eliminate a lot of those flags

thin aurora
#

If you don't know what it does, it's not a good idea to use it

latent latch
#

ref is fine if you're passing structs into methods

#

otherwise just make classes

thin aurora
#

If you have to pass structs by reference and you don't know what ref is then that's a good candidate for refactoring in general

#

It also ruins the idea of a struct

azure frost
thin aurora
#

Why do you use ref here, though?

#

Ah, more code

azure frost
#

That's the way KinematicCharacterController had it.

thin aurora
#

You don't mutate the value, why did you add ref here?

#

You can just pass it by value

arctic sparrow
#

That's how it was originally. Seek is still learning how this all works

thin aurora
#

Then I would just remove it

#

If your other script requires mutation of this object then I suggest you get a reference to the class directly and mutate it from there

#

There's very little reason to actually use ref

#

Not because it's "bad". ref is very specific and generally you should just use another approach

#

I think Mao generally gave a good answer too. You probably just want to use a class here.

latent latch
#

Ok, so this is probably what's happening. Every frame it's making a new Input struct

#

and because it's being read every frame, Crouch is being acted upon even if the value isn't being set explicitly by the player

quartz folio
#

the same thing would happen whether it was a class or a struct because it's just being newed every frame

latent latch
#

right, so the bool value is by default false and that's what's being read into the input

quartz folio
#

store the state of the crouch at the ExamplePlayer class, and set a toggled version of that to the input struct

arctic sparrow
#

So if we only initialized the class/struct once, then we could have the variables be persistent?

quartz folio
#

The design of the example input is stateless. You have to add your own state, just set the crouch input based on a bool you yourself control at the class level

latent latch
#

KC is pretty good, but such a pain to get it working with cinemachine cause there's a lot of it is hardcoded for the basic main camera

azure frost
#

Okay, it is fixed!

visual pollen
#

Hey, wanted to ask for some tips or ideas on something im trying to do.

My current goal is to have a slider where I can drag, and if it reaches max or min value, it can loop around. Visually the slider will be radial in nature. Any ideas how I should go about the looping aspect? I dont need direct code, just ideas or opinions on how to tackle the issue

fiery spruce
fiery spruce
#

Didn’t realize that’s a thing, cool

visual pollen
#

Aight thanks! Ill test both out! Also agreed, never knew Mathf.Repeat was a thing! Cheers you lot

copper glade
#

I'm developing a 2D game, primarily focused on UI, and I'm looking for a better way to save and load game states. Currently, I have a lot of UI elements and game objects that need to be saved. My current approach is to manually serialize each script's data to JSON and then load it back when the game resumes. This works, but it's very cumbersome and requires manual updates to the saving and loading logic every time I change my UI or game logic.

My game consists of several mini-games, so I end up having separate saving/loading systems for each one. I'm hoping to find a solution that's more automated and less error-prone. I'm working offline and only need to save locally.

Is there a package or resource you would recommend for saving and loading complex 2D UI scenes? I'm looking for a solution that avoids me having to write all the saving and loading logic manually.

Any help would be appreciated!

plucky inlet
#

And when then loaded, the script will just onenable check itself inside that list and get its values from there

knotty sun
steady bobcat
#

every time

copper glade
knotty sun
# copper glade which one?

without knowing exactly what you are doing I'm guessing the Core asset and the UI Add-on will do the job
You might want to look at the Core+ bundle as it has a 50% New Release discount atm

azure frost
#

So, in the Kinematic Character Controller, where in the scripts is the value that determines which direction the player is facing?

arctic sparrow
#

Seek, I literally said to follow the movement values from the inputs class.

wintry crescent
#

What are some recommendations from people here, for serialized dictionary packages?

#

I need a good one, and there's plenty, but I don't know how to choose

#

and last time I tried to find one myself, I couldn't find a good one

#

ideally not paid, or at least cheap

thin aurora
#

I assume this is binary serialization or just being able to show them in the inspector?

wintry crescent
trim schooner
#

IIRC Odin does it, and that's the best

thin aurora
#

I can imagine this is a pretty common problem which has a free solution

wintry crescent
trim schooner
#

dunno, go look

thin aurora
wintry crescent
leaden solstice
#

I wouldn’t really recommend Odin for it

wintry crescent
#

last I tried that it ended up shit

#

and had to remove it

#

I want a recommendation

#

can't count on google for that

#

not these days for sure

thin aurora
#

Lol

wintry crescent
thin aurora
#

At least try it before you judge

wintry crescent
#

I tried a bunch a while ago

thin aurora
#

Did you try this one?

wintry crescent
#

and got tired searching for a solution that didn't require modifications to work and wasn't crap

#

I dunno it was a while ago, I am asking for a recommendation from someone who uses a serialized dictionary package

#

so that I don't have to try 20 of them

thin aurora
#

This package averages nearly 5 stars. I would just try it

leaden solstice
wintry crescent
#

I'm not asking for a lot, please I just want a recommendation from someone who actually uses one

azure frost
wintry crescent
#

please dont recommend me random things you find on google

#

please

#

if you don't use one, please

#

I am not looking for the top 5 google results right now

#

because I already tried a bunch and they were crap

#

so I'm asking for someone who knows what they're talking about

#

to recommend me something

leaden solstice
wintry crescent
leaden solstice
#

Just answer?

wintry crescent
#

holy crap friends this is insanely unproductive I am just asking for someone who is already using one to say what they're using and if it's any good

#

that's really not much to ask for

thick terrace
fleet gorge
#

I make my own serialised dictionary

leaden solstice
#

So hard to say what is your detailed usecase and what you want

wintry crescent
#

yea is it any good

leaden solstice
#

Lol

wintry crescent
#

which ones have you tried?

thin aurora
#

Generally Google results by relevancy so the first few results are the best ones

wintry crescent
#

I'm looking for people who tried them I said it like 10 times now

fleet gorge
#

I already tried the top results, I ended up making my own

#

Doesn't take very long

leaden solstice
#

Just stuff them in List

wintry crescent
leaden solstice
#

Load as Dictionary at some point

fleet gorge
#

Coming from someone who's already tried it

#

Just diy

thin aurora
#

You instantly shoot down suggestions, but generally these work fine

wintry crescent
# fleet gorge There's no other libraries

this is the type of thing I'm looking for
someone who also looked for it and went through the pain
Ideally I'd find a premade package but if it's not possible then I guess I gotta make one myself although I wanted to avoid it

trim schooner
#

There are loads of reviews on that one for you to get a wider range of opinions on it too

fleet gorge
#

yea I'll just share my experience

wintry crescent
#

you don't have to understand my thought process

fleet gorge
#

my experience is that all the packages do too much

#

it's not worth asking around

#

everyone makes their own

trim schooner
#

I'd wager more people use a premade one than make their own

trim schooner
tawny elkBOT
fleet gorge
leaden solstice
#

I have no idea who the hell is Chirz

plucky inlet
azure frost
# fleet gorge How may we help?

Well, Chirz (@arctic sparrow ) was trying to use the player's current orientation to recenter the camera with. But it didn't seem to work no matter what we set the input to.

fleet gorge
#

What do you have so far

fleet gorge
#

I don't see any code for changing the orientation of the camera

plucky inlet
#

I guess, the missing part is inside this method... CharacterCamera.UpdateWithInput(Time.deltaTime, scrollInput, lookInputVector);

azure frost
#

Here's ExampleCharacterCamera

plucky inlet
#

Id say, add a bunch of debug.logs first and see, if all your if clauses are actually working as they should

arctic sparrow
#
if(InputMod.GetButtonDown(CenterCamInput)) characterInputs.CameraRotation = CharacterCamera.Transform.rotation = Character.transform.rotation;

Wait, I think we might be looking at it the wrong way. It's in the HandleCharacterInput function instead of the HandleCameraInput function

plucky inlet
#

And what are those random brackets?

leaden solstice
#

The scope

#

I guess

plucky inlet
#

Phew, hurts me personally, but that might just be my preference to not to 😄

fleet gorge
#

you guess?

#

who's the one who wrote this code

#

on a scale of 1-10 how much do you understand the code you wrote

plucky inlet
#

its from the question from chirz and seekingthesky

leaden solstice
#

Not me, apparently

fleet gorge
plucky inlet
#

Not sure chatgpt would write uppercase camelcase mixtures, but could be

trim schooner
leaden solstice
fleet gorge
#

ah

azure frost
plucky inlet
arctic sparrow
plucky inlet
arctic sparrow
#

Still working on it

#

OK! I found a fix!

#
if(InputMod.GetButtonDown(CenterCamInput)) CharacterCamera.PlanarDirection = Character.transform.forward;
#

"CharacterCamera.PlanarDirection" was one of the values leading into determining the camera's rotation.

quartz folio
plucky inlet
quartz folio
#

Pascal for public, underscore camel for private, yes

plucky inlet
#

Guess I have been too much into unity scripts then 😄

plucky inlet
quartz folio
#

Because Unity is very old

plucky inlet
#

Haha, funny, I thought that _ thing was very old as it remembers me of very very old scripts I wrote back then

quartz folio
#

All new packages use the correct conventions, but the built-in code does not because it's a legacy codebase with that old style

plucky inlet
#

thanks for enlighting me here! 🙂 guess I will start the next project with those conventions correctly then

thin aurora
#

Isn't the convention in Unity like this because they used to support a javascript-like language that had these conventions?

#

Which is obviously long gone, but now this remains

placid summit
#

ugh _ is an odd convention when IDEs now color code for private public

quartz folio
#

They also use Hungarian notation

#

Which has nothing to do with JavaScript-likes. It's just a really old codebase with very old decisions

thin aurora
quartz folio
placid summit
sleek bough
quartz folio
#

I used to use Unity's conventions, then I switched, and imo it's nicer to use C#'s because then you feel more comfortable when working externally where that convention is practically saturated

sleek bough
#

But personally I don't like using it for aesthetics and trying avoiding classes get so large that I need that :D

thin aurora
placid summit
quartz folio
#

Some people don't have class and struct type names highlighted differently and that freaks me out

thin aurora
#

I might turn that on then. I think the conventions are still very useful for the reasons listed, but it's definitely an added step in readability

placid summit
#

What I do not like is Unity's old camelCase properties which have long been wrong

#

Is there a convention of not always using properties in structs like with Vector3?

thin aurora
#

VS supports analyzers using .editorconfig files. I believe it also has conventions for that

#

Though it might suggest properties rather than fields, which is the opposite in your case

quartz folio
#

Structs don't necessarily need to protect input because usually they're not doing work, so a property would be unnecessary overhead

placid summit
quartz folio
#

In the past Unity does very little method inlining

#

The Vector structs don't care if you assign X as 1 or 29, it's just data, what good would a property do

#

Any float is valid, without context it's just raw data

placid summit
#

There is no reason to use a Property in many class cases but it is standard practice afaik. Was not sure if differes for structs

quartz folio
#

It's only standard to avoid making breaking API changes

#

If you've got nobody consuming an API, then it's a practice ready to be dropped

placid summit
quartz folio
#

They haven't updated that doc in a long time so I would expect certain things to have changed

#

Also this is a micro optimisation in most cases

placid summit
#

indeed

chilly surge
#

A field's getter and setter accessibilities are tied together. If you want to have public getter and private setter for example, then property is the only way.

#

Interface can contain properties but not fields. This means that if you need to latter add an interface to an existing class, you don't need to refactor anything.

#

It's unfortunate that Unity's serialization doesn't play very well with properties, that property vs field is even a choice we have to consider.

placid summit
#

you can serialize the field but will have odd name if not full property

wheat spruce
#

I've got this code that lets you swing the back object around the front.

private void OrbitWheels()
{
  _orbitSpeed += (_aimDirection != Vector2.zero ? 1 : -1) * _speedRate * Time.fixedDeltaTime;
  _orbitSpeed = Mathf.Clamp(_orbitSpeed, 0f, _maxOrbitSpeed);

  Vector2 sideForce = _aimDirection;
  Vector2 force = transform.TransformDirection(sideForce) * _orbitSpeed;
  _rb.AddForce(force, ForceMode2D.Force);
}```The issue is the orbit direction starts to become confusing when you face other directions instead of moving up. At the start Left/Right makes sense, but at the end when you move downwards, Left/Right become inverted
#

_aimDirection is set with the arrow keys, so it really should be able to use the correct key based on the direction you are heading

maiden fractal
late lion
wheat spruce
#

well, offrail

copper rose
#

what do you think guys for a first person game, its better to manage the camera as children of player or both separate gameobjects? i cannot get working smoothly the gamepad, it wors fine mouse only, and maybe its a better approach to add camera as children ?

atomic kindle
#

my gs how do I read a playerpref registry file

#

I tried google

#

let me try again

#

not as in find it as in read the value of it

wintry crescent
#

is there a difference between transform as RectTransform or (RectTransform)transform?

quick token
quick token
#

they're the same thing

#

the second one is a typecast

#

oh wait, i misread

wintry crescent
maiden fractal
atomic kindle
#

i used hexadecimal

#

I just yoloed and it worked

maiden fractal
atomic kindle
#

anyways I have a bigger problem

#

I set this to "hey:

#

"hey"

#

and this outputs null and saveslot 1

maiden fractal
#

plain text username and password

atomic kindle
#

sorry I dont understand?

wintry crescent
quick token
# wintry crescent some context:

https://stackoverflow.com/questions/132445/direct-casting-vs-as-operator

string s = (string)o; // 1
Throws InvalidCastException if o is not a string. Otherwise, assigns o to s, even if o is null.

string s = o as string; // 2
Assigns null to s if o is not a string or if o is null. For this reason, you cannot use it with value types (the operator could never return null in that case). Otherwise, assigns o to s.

string s = o.ToString(); // 3
Causes a NullReferenceException if o is null. Assigns whatever o.ToString() returns to s, no matter what type o is.

Use 1 for most conversions - it's simple and straightforward. I tend to almost never use 2 since if something is not the right type, I usually expect an exception to occur. I have only seen a need for this return-null type of functionality with badly designed libraries which use error codes (e.g. return null = error, instead of using exceptions).

3 is not a cast and is just a method invocation. Use it for when you need the string representation of a non-string object.
(i think this explains it)

maiden fractal
atomic kindle
#

for proof that its hey in the registry

wintry crescent
wintry crescent
atomic kindle
#

oh shooot I sent both getstrings

#

hold on

wintry crescent
# atomic kindle

and you're absolutely 100% sure that Save.selectedSaveSlot is the same

#

like dead sure

atomic kindle
#

its a static variable that is not edited anywhere else

#

public void Submit(string type)
{
user = username.text.ToString();
pass = password.text.ToString();

    if(type == "login")
    {
        Debug.Log(PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username"));
        Debug.Log(PlayerPrefs.GetString(Save.selectedSaveSlot + "_Password"));
        if(PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username") == name && PlayerPrefs.GetString(Save.selectedSaveSlot + "_Password") == pass)
            {
                SceneManager.LoadScene(4);
            } 
            else
            {
                Debug.Log("Wrong password or username");
            }
        
    }
    if(type == "signup")
    {
        PlayerPrefs.SetString(Save.selectedSaveSlot + "_Username", user);
        PlayerPrefs.SetString(Save.selectedSaveSlot + "_Password", pass);
        Instantiate(signUpConfirm, mainCanvas.transform);
        Invoke("ConfirmSignup", 2.0f);

    }
    
    
}
quick token
#

!code

tawny elkBOT
tawny elkBOT
quick token
#

hah, beat you to it sunglus

plucky inlet
#

woops 😄

atomic kindle
#
public void Submit(string type)
    {
        user = username.text.ToString();
        pass = password.text.ToString(); 

        if(type == "login")
        {
            Debug.Log(PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username"));
            Debug.Log(PlayerPrefs.GetString(Save.selectedSaveSlot + "_Password"));
            if(PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username") == name && PlayerPrefs.GetString(Save.selectedSaveSlot + "_Password") == pass)
                {
                    SceneManager.LoadScene(4);
                } 
                else
                {
                    Debug.Log("Wrong password or username");
                }
            
        }
        if(type == "signup")
        {
            PlayerPrefs.SetString(Save.selectedSaveSlot + "_Username", user);
            PlayerPrefs.SetString(Save.selectedSaveSlot + "_Password", pass);
            Instantiate(signUpConfirm, mainCanvas.transform);
            Invoke("ConfirmSignup", 2.0f);

        }
        
        
    }
plucky inlet
# atomic kindle

can you store your playerprefs get in a string before logging it?

atomic kindle
#

I signed up first

#

so its saved

#

to hey

plucky inlet
#
string yourName = PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username");
Debug.Log(yourName);
wintry crescent
#

like if you do signup and login now, this should work

thin aurora
# wintry crescent some context:

That's something you can check by diving into the definition of RectTransform. I assume it has an implicit conversion from transform or this code would throw

#

Alternatively transform is already a RectTransform here. I believe this is in 2d?

#

So transform's actual type is a base type for both 2d and 3d

wintry crescent
#

but I think you don't understand what I mean here, I wanted to know the differences between those two ways to cast transform to recttransform, my question was answered

atomic kindle
#

comes out as this

wintry crescent
#

they're effectively the same for my purpose

atomic kindle
atomic kindle
wintry crescent
# atomic kindle

try giving it a default value perhaps? to check if it's saved as a space or sth, or if it's reading an unsaved value

thin aurora
atomic kindle
#

yourName?

wintry crescent
thin aurora
#

Pattern matching is another way to match against a type, just like casting

atomic kindle
#

OK guys, I think I got it figured out

wintry crescent
# atomic kindle give what a default value?

yeah just for testing, do something like this
PlayerPrefs.SetString(Save.selectedSaveSlot + "_Username", user);
Debug.Log(PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username", "nothing was saved"));

wintry crescent
atomic kindle
#

turns out this was not the issue

#

its the if statement that doesnt show true

#

for some reason

plucky inlet
#

I think, playerprefs is not "done" when logging it, so you get null/nothing

gilded monolith
#

does anyone know how to lock cursor to a certain position?

atomic kindle
plucky inlet
wintry crescent
#

Cursor.lockState = CursorLockMode.Locked;

#

otherwise? don't.

atomic kindle
wintry crescent
atomic kindle
#
 string yourName = PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username");
            Debug.Log(user);
            Debug.Log("prefs: " + yourName);
            string yourPass = PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username");
            Debug.Log(user);
            Debug.Log("prefs: " + yourPass);
            
            if(PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username") == name && PlayerPrefs.GetString(Save.selectedSaveSlot + "_Password") == pass)
atomic kindle
#

WHY????

#

THEY'RE LITERALLY THE SAME

plucky inlet
#

Equals == true?

wintry crescent
plucky inlet
#

Hidden unicode? 😄

atomic kindle
wintry crescent
atomic kindle
#
    public void Submit(string type)
    {
        user = username.text.ToString();
        pass = password.text.ToString(); 

        if(type == "login")
        {
            string yourName = PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username");
            Debug.Log(user);
            Debug.Log("prefs: " + yourName);
            string yourPass = PlayerPrefs.GetString(Save.selectedSaveSlot + "_Username");
            Debug.Log(user);
            Debug.Log("prefs: " + yourPass);
            
            if(yourName == name && yourPass == pass)
                {
                    SceneManager.LoadScene(4);
                } 
                else
                {
                    Debug.Log("Wrong password or username");
                }
            
        }
        if(type == "signup")
        {
            PlayerPrefs.SetString(Save.selectedSaveSlot + "_Username", user);
            PlayerPrefs.SetString(Save.selectedSaveSlot + "_Password", pass);
            Instantiate(signUpConfirm, mainCanvas.transform);
            Invoke("ConfirmSignup", 2.0f);

        }
        
        
    }
#

it literally both uses user

#

so it doesnt make sense

#

its like asking if user == user and getting false

wintry crescent
atomic kindle
#

if this works istg

wintry crescent
atomic kindle
#

No sir

thin aurora
#

You should not be comparing strings like this. Strings in C# have build in systems that increase performance by reusing them. The reason yours are not used is because they are not reusing the same string instance most likely

#

So instead of if (a == b), use if (a.Equals(b))

atomic kindle
#

OK

#

brb

wintry crescent
#

good idea actually yeah

#

worth a try

thin aurora
#

Also pointing out the obvious, but if a person applies a single character with different casing, it will also fail. name != Name. I assume you understand this

wintry crescent
#

for password obviously, but even for the name

thick terrace
thin aurora
atomic kindle
#

Im restarted

wintry crescent
atomic kindle
wintry crescent
atomic kindle
thin aurora
atomic kindle
#

I'll just to lower them both like this

#

or is that not good

thin aurora
#

This isn't just by defining how casing works. There are certain cultures where in one case a string might mean the came, but in others it does not

#

Like weird characters with symbols above them. I don't have a direct example

knotty sun
atomic kindle
#

OK

thin aurora
#

No need for ToLower or anything like that

#

if(yourName.Equals(user, StringComparison.OrdinalIgnoreCase) ...

thin aurora
#

This is generally how string comparison is done

atomic kindle
#

I'll always use .equals from now, thank you sir for teaching me a lifelong lesson

#

genuinely forgot about allat equals stuff

thin aurora
#

It's not applicable literally everywhere. You might want to use ToLowerInvariant or ToUpperInvariant in cases for normalization or something

#

Fun fact, you should actually use ToUpperInvariant because ToLowerInvariant and the other non invariant versions have unexpected quirks to them

atomic kindle
#

OK

#

wait but I did ignorecase not toupper

thin aurora
#

That's better suited for this use case, yes

thick terrace
#

ToUpper/ToLower involve copying the characters into a newly allocated string, passing in the the comparison type changes the comparison logic without needing to do that

atomic kindle
#
    private void CheckLetterInput()
    {
        foreach(Key key in keys)
        {

            if (Input.GetKeyDown(key.ID))
            {
                PressKey();
            }

            if (Input.GetKeyUp(key.ID))
            {
                ReleaseKey();
            }
        }  
    }
    private void PressKey()
    {
        foreach(Key key in keys)
        {
            if (key.CheckKey())

                key.IsPressed();
        }
    }

    private void ReleaseKey()
    {

        foreach (Key key in keys)
        {
            if (key.CheckKey())

                key.IsReleased();
        }
    }
#
    public void IsPressed()
    {
        gameObject.GetComponent<SpriteRenderer>().sprite = keyPressedAlt;
    }

    public void IsReleased()
    {
        Debug.Log("hi");
        gameObject.GetComponent<SpriteRenderer>().sprite = keyPressed;
    }
#

anyone know why this doesnt work?

#

"hi" doesnt show up in the console

#

meaning that key.CheckKey isn't true for release key while it is true for presskey??

#

hard to understand

thin aurora
#

Time for clarity then

#

Start logging the values, see if they return what you expect

#

If you think the issue is key.CheckKey, then debug what the value returns

#

First thing you always do is pinpoint the exact part of the code with the issue

atomic kindle
#

understood sir

#

the foreach part works

#

ok

#

using this

#

the first checkkey for presskey is true then 25 falses

#

but all checkkeys are falses for releasekey

knotty sun
#

would it not have been sensible to log which key you were checking?

atomic kindle
#

oh to print all keys?

#

ok

#

OK. I pressed the w key which was right and the presskey got it

#

however, release key always seems to start form Q

#

actually nvm

#

it just doesnt work

#

checkkey returns true for presskey

#

but doesnt for release key

#

even if the same P is entered

thin aurora
#

Keep on rubber ducking

knotty sun
#

and type in full sentences

atomic kindle
#

This is checkkey btw, for clarification

thin aurora
#

Looks good to me chief

atomic kindle
#

This is so weird. They both are the exact same methods, so it doesn't make sense that one is returning false while the other is returning true.

thin aurora
#

I don't get why you overcomplicate it so much

#

Is Key your own class?

atomic kindle
#

Yes

thin aurora
#

Why do you have that?

atomic kindle
#

I have 26 gameobjects to create a keyboard

thin aurora
#

Oh, this is a game keyboard?

atomic kindle
#

Yes

thin aurora
#

Understandable

atomic kindle
#

is pressed and is released are supposed to be to change the sprite of the key, pressed down and greyed out or not

#

Theres literally nothing more to uncover. Its clear that everything is working, but that CheckKey is not returning true for ReleaseKey for some reason, but the why is unknown

#

I personally think its a problem with getkeyupo

#

but I don't know if theres anything I can use other than GetKeyUp for this

#
private void CheckLetterInput()
    {
        foreach(Key key in keys)
        {

            if (Input.GetKeyDown(key.ID))
            {
                PressKey();
                Debug.Log("hi");
            }

            if (Input.GetKeyUp(key.ID))
            {
                ReleaseKey();
                Debug.Log("hi1");
            }
        }  
    }
#
private void PressKey()
    {
        foreach(Key key in keys)
        {
            Debug.Log(key);
            Debug.Log(key.CheckKey());
            if (key.CheckKey())

                key.IsPressed();
        }
    }

    private void ReleaseKey()
    {
        foreach (Key key in keys)
        {
            Debug.Log(key + "1");
            Debug.Log(key.CheckKey() + "1");
            if (key.CheckKey())

                key.IsReleased();
        }
    }
#
public bool CheckKey()
    {

        return Input.inputString.Equals(ID, System.StringComparison.OrdinalIgnoreCase);
    }
#

I GOT IT

#

The inputstring will be empty when I let the key go

#

duhhhhhh so then if checkkey is called during the time when the key is released, then ofcourse the inputstring will be nothing!

#

so I need an input for checkkey

#

Thanks for letting me rubberduck yall

#

also do I need reload domain opn it takes so long every time. When can I disable it?

#

Ok new problem

#

this works but removing the debugs makes it not work anymore, specifically the debuglog on the top

knotty sun
#

do you not know how to write an if statement?

atomic kindle
#

Holdon this doesnt work?

knotty sun
#

think about it, what is the difference in logic with and without the Debug statement