#archived-code-general

1 messages ยท Page 309 of 1

hard viper
#

tbf, very important setting to get right

fervent arrow
spring creek
fervent arrow
#

I think

#

Idk

#

I dont have ultra superhuman vision

spring creek
#

At the bottom of the inspector, in the preview

fervent arrow
past kite
#

I use a lot of decorators for my ScriptableObjects:

public interface IBla {
    int Num{ get; }
}

public interface IFoo {
    int Str{ get; }
}

public class FooAbleMonster : ScriptableObject, IBla, IFoo {
    public int Num => 3;
    public int Str => "hello";
}

public class BaseMonster : ScriptableObject, IBla {
    public int Num => 2;
}

Different SOs implement different interfaces, but a lot of them share them. No multiple inheritance, so I can't use classes instead of interfaces.

Is there a framework in c# to include implementations from files? Something like aspect-oriented programming?

#

Basically I want to implement some code templates for the different interfaces and get them copied into classes.

thick terrace
past kite
thick terrace
#

it's new-ish but should be supported in unity 2021+ i think?

past kite
#

it clearly breaks the idea of an interface as you are now providing implementation with the interface, but I don't care, because I'm not a language purist.

thick terrace
#

well, you can only define it in terms of the public interface, so it's not really much more powerful than defining extension methods on an interface like you could before

past kite
#

well, the problem I now run into is that I cannot define a field in the interface that is used in the default implementation. So it seems it won't work.

thick terrace
#

๐Ÿค” you mean a property?

past kite
#

Either would be fine, because I would define the getter as part of the interface.

#

public interface IBla {
    int Num{ get; }
}

public interface IFoo {
    int Str{ get; }
}

public class FooAbleMonster : ScriptableObject, IBla, IFoo {
    [SerializeField] private int _num;
    public int Num => _num;

    [SerializeField] private int _str;
    public int Str => _str;
}

public class BaseMonster : ScriptableObject, IBla {
    [SerializeField] private int _num;
    public int Num => _num;
}

This is what the code looks like. Default interfaces don't support defining _num or _str, which I can then edit through the inspector.

#

As you can see, I constantly copy&paste the interface implementations into the different SOs.

thick terrace
#

oh i see, yes you would still have to implement the interface in each case

#

to do that kind of thing normally i guess you'd just make a separate class or struct for those fields? if a bunch of things have the same set of data fields, better to put that data in its own type definition rather than try to get the compiler to do it for you

#

basically composition instead of inheritance

past kite
#

Composition is what I'm trying with using interfaces. I can slap on as many interfaces as I want. In the MonoScripts, I then just cast the object to the interface to use them. So I can define BlaCapability and it gets the base object with IBla so = GetComponent<...>().so as IBla;.

thick terrace
#

you could make IBla into IHasBla which has a getter for a Bla , but then you don't need to copy all the fields to each implementation, you just need to give them a Bla property

past kite
#

Can you give a short example? I don't fully get it.

thick terrace
# past kite Can you give a short example? I don't fully get it.

sorry, i don't have time to come up with a full example right now, but basically assuming you have more than one property in your real interfaces, put all those properties in a struct instead so you only need to add one field per interface instead of all the fields, and you can still access them through default methods on the interface

past kite
haughty glacier
#

I'm making a Rock Paper Scissors simulator that is feature rich. I want to be able to do various things with it, such as mazes, RPSLS ||Rock, Paper, Scissors, Lizard, Spock|| and skills. but the issue I'm running into is the code I have and pathfinder I'm using are inefficient and even 60 entities are too many and it stays frozen. what I currently have, each entity will look through all the other entities and will look for targets and enemies. if a enemy is closer it will run away. if a target is closer it will chase it.
here's my project on GitHub:
https://github.com/StoneCommander/TwitchRPS

GitHub

Twitch RPS interactive game! Contribute to StoneCommander/TwitchRPS development by creating an account on GitHub.

fervent furnace
#
void Update(){
  // ***** TARGET *****
  
  // get all entity objects
  GameObject[] entities = GameObject.FindGameObjectsWithTag("entity");
  attackTargets = new List<Vector2>();
  runTargets = new List<Vector2>();
  foreach (GameObject entity in entities){
    Entity entityScript = entity.GetComponent<Entity>();
    // check if enitty type is on the attack types list
    if(attackTypes.Contains(entityScript.type)){
      print(entity.transform);
      attackTargets.Add(entity.transform.position);
    }
    // check if enitty type is on the run away types list
    else if(runAwayTypes.Contains(entityScript.type)){
      print(entity.transform);
      runTargets.Add(entity.transform.position);
    }
  }
  //other codes
}
#

you have 60 entities, so the above code runs 60 time per frame

#

now look into this

// check if enitty type is on the attack types list
if(attackTypes.Contains(entityScript.type)){
}
// check if enitty type is on the run away types list
else if(runAwayTypes.Contains(entityScript.type)){
}
```we know that Contain costs O(n) time to look up that means 
```cs
foreach (GameObject entity in entities){
  some list.contains()    
}
```is O(n^2)
#

you cpu may still be handle it and other stuff within 16ms, but you should optimize it as much as you can

#
List<Vector2> ShortenPath(List<Vector2> path){
  List<Vector2> newPath = new List<Vector2>();
  for (int i=0;i<path.Count;i++){
    newPath.Add(path[i]);
    for (int j=path.Count-1;j>i;j-- ){
      if(!Physics2D.Linecast(path[i],path[j], obstacles)){     
        i = j;
        break;
      }
    }
    newPath.Add(path[i]);
  }
  newPath.Add(path[path.Count - 1]);
  return newPath;
}
```also this is called every frame
#

oh nvm, this should be done in linear time

#
list.add(point[0]);
lastPoint=point[0];
for(int j=1;j<count;++j){
  if(point at j is visible from lastPoint&&j<count-1){
    continue;
  }
  list.add(point[j]);
  lastPoint=point[j];
}
hardy mulch
#

Anyone have an implementation for Mathf.HalfToFloat (and Mathf.FloatToHalf)? I need to do some conversions outside of the unity context and thus don't have access to Mathf

rotund ember
#

Anyone know a good way to add collisions to big enemies that work with IK want to make it collidable with my player but because it uses skin mesh render I cant think of a good way to do it

cosmic rain
hardy mulch
#

I did look it up, I found the built in Half struct, but I don't think im using it correctly

#

I attempted to implement like this:

        public static ushort FloatToHalf(float val)
        {
            return (ushort)(Half)(val);
        }

        public static float HalfToFloat(ushort val)
        {
            return (float)(Half)(val);
        }

#

But did not get correct results out of it

dim latch
#

What would be the best way to go about getting a list of every script that inherits an interface?

    public class NetworkUtils : MonoBehaviour, HasUtilities
    {
        public string utilityName { get; } = "Network";
        public UtilityAction[] SetUtilities { get; } =
        {
            new UtilityAction("Test Action", () =>
            {
                Debug.Log("thing pressed");
            }),
        };
    }

This is an example script i made, so id like to get all scripts that have HasUtilities and then access the values. I thought of using FindObjectsOfType but that only works for scripts in the scene, whereas i also have some utils that are just static

fervent furnace
#

is HasUtilities interface?

spring creek
hardy mulch
#

It is not good enough, the numbers are wrong

fervent furnace
#

raw implementation

dim latch
hardy mulch
soft shard
dim latch
fervent furnace
#

why your float to half returns ushort?

hardy mulch
#

Because thats what Mathf.FloatToHalf returns, a Half is just a convince for a ushort

fervent furnace
#

half is not ushort

#

oh unity convert it to ushort

hardy mulch
#

Sure but they're the same size, ushort is typically what things pass half's around as

#

And its what the unity Mathf lib uses, and its the data type im receiving/dealing with

soft shard
dim latch
#

Hmmm, maybe i should just bite the bullet and add all the scripts with HasUtilities to a gameobject in the scene then

#

I guess it wouldn't be too bad

soft shard
soft shard
dim latch
#

Thanks for the help :)

twilit scaffold
#

Out of curiosity, is there a built way, or a tool, to covert Visual Scripting to native C#?

runic nimbus
#

I have a quick question about how you might go about modifying the stats of a gun through attachments
So I have my WeaponStats struct ranging from stuff like whether the gun is full auto, the recoil values, etc, and a bunch of attachments that can arbitrarily modify the weapon stats

#

In my previous system, it was easy to do this. You simply ran through each modified stat and multiplied it by the original. Easy.

#

Things are more complicated now though, as you can detatch attachments mid game. Now, how would I go about "reverting" the stats that were changed?

#

This isn't as simple as setting it all to the original stats, as attachments only modify select stats

#

Another thing to consider is that I'm also not just multiplying values anymore, there are bools and sometimes an attachment may want to set a stat to a certain value.

chilly surge
#

Your final weapon stats is just a combination of the base stats and all the attachments right? Shouldn't it simply be anytime your attachments changes, whether it's a new one being added or an old one getting removed, just recalculate the whole thing again?

runic nimbus
#

Oh, good idea. I can just have it recalculate everything upon adding and removal.

#

Thanks

upper pilot
#

My Game class is created 2 times, could it be due to DontDestroyOnLoad?
It causes some of the properties to be null, which makes no sense as those properties should never be null(they are created with data with the object)
I am lost ๐Ÿ˜

spring flame
#

are you using a constructor and it's inheriting from MonoBehavior or Component?

upper pilot
#

its inheriting from MonoBehaviour

#

and I do use a constructor for testing, its called 2 times.

#
public abstract class PersistentSingleton<T> : Singleton<T> where T : SerializedMonoBehaviour
{
    protected override void Awake()
    {
        base.Awake();
        DontDestroyOnLoad(gameObject);
    }
}
#

Even if I remove singleton code and just use MonoBehavior:

#

public class Game : MonoBehaviour
{
    public static Game Instance;
    public Game()
    {
         Debug.Log("Game created");
    }
    private void Awake()
    {
        Instance = this;
        Debug.Log("Awake called");
    }
}
#

So its interesting, that 1st call doesnt even go to Awake method, but only constructor runs once.

#

Any ideas what could cause this?

#

That solved it, removed inline initializers from Game class as well as a constructor and I initialize it in Awake.
All other component of the game can still use constructors/inline initializers, the only objects that cant use those are Monobehaviours due to how playmode works.

hexed fjord
#

My player can only move right? This is for android

{
    if (Input.touchCount > 0)
    {
        if (EventSystem.current.IsPointerOverGameObject(Input.touches[0].fingerId))
            player.x = moveX;
    }
    else
        player.x = 0;
}```
moveX is properly set as negative for the left button, but it still makes you go right anyways
```void Update()
{
    Vector3 move = new Vector3(x, 0, 1);
    rb.MovePosition(transform.position + move * speed * Time.deltaTime);
}```
upper pilot
#

What is the issue here?

#

if moveX is negative, shouldnt it move left?

#

unless speed is also negative then -1 * -1 = 1

hexed fjord
#

right is set as 0.5f, moves right
left is set as -0.5f, also moves right

upper pilot
#

I am confused about your code, 2 scripts seem to do different things

#

player.x = moveX will set your position to moveX value

#

Either way, you should debug the code, are you sure that its -0.5f and 0.5f when you actually move in game?

leaden ice
#

Nothing in this code sets it

upper pilot
#

or x

leaden ice
#

I assume that's from the "player.x = moveX" bit

#

But if moveX is just some constant positive value that explains things

upper pilot
#

we can assume ๐Ÿ˜› But if this is copy paste code then it doesnt seem to do what its supposed to do.

hexed fjord
#

moveX is a public float, the touch code goes in each of the UI buttons

leaden ice
#

So obviously you can only go right

#

How do you get any expectation of being able to go left from that code? Seems like wishful thinking is the only thing powering that.

hexed fjord
#

do you know what a public variable is? it lets you set different values on each object that has the code

#

like this

leaden ice
#

Of course, and presumably the copy of the script your other script is referring to has a positive value there.

#

Also Rigidbody.MovePosition should never be used in Update like that.

#

It's going to lead to buggy/stuttering motion

leaden ice
hexed fjord
#

yes, but not at the same time as they are buttons

leaden ice
#

So it doesn't mattr which one you press, whichevers Update runs second will win out

leaden ice
#

You're doing a weird broken thing in Update

#

It's going to be true for both of them

#

They are both going to run at the same time

#

Your code is just checking if you're touching ANY UI element

hexed fjord
#

hmm so the touch detection is the one with the error?

leaden ice
#

Not this particular button

hexed fjord
#

makes sense

leaden ice
#

Yes, you should be using IPointerDownHandler and IPointerUpHandler

fervent arrow
#

Guys what is this "unity charging you" thing about?

leaden ice
#

Hello time traveler

#

Welcome to 8 months in the future

#

All that hubbub is over with.

#

(also that's not related to code)

oblique spoke
tardy crypt
#

Itโ€™s basically a non issue for anybody that comes and posts here anywayโ€ฆ

knotty sun
#

Damn straight, the chances of anyone posting here of ever having to pay Unity anything are as close to zero as to be negligible

swift cobalt
#

HI

I am trying to generate meshes through code, based on received data, including the Contour Points and the Center Point of the mesh. The created mesh doesnt seem to be right and the center is off. Down you can find the code and the result mesh

public void GenerateMesh(ObjectData data)
    {
        List<Point> contourPoints;
        Vector3 centerPosition;
        Mesh mesh;

        Debug.Log("Generating Mesh...");

        contourPoints = data.contour_points;
        centerPosition = new Vector3(data.x, data.z, data.y);

        mesh = new Mesh()
        {
            name = "Mesh"+data.object_id.ToString()
        };

        GetComponent<MeshFilter>().mesh = mesh;

        Vector3[] vertices = new Vector3[contourPoints.Count];
        for (int i = 0; i < contourPoints.Count; i++)
        {
            //The points are 2D so we are using the Z position of the provided center point for our vertices
            vertices[i] = new Vector3(contourPoints[i].x, contourPoints[i].y, centerPosition.z);
        }

        //Creating triangles from the provided vertices, assuming the contour points form a closed loop
        int[] triangles = new int[(contourPoints.Count - 2) * 3];
        for (int i = 0; i < contourPoints.Count - 2; i++)
        {
            triangles[i * 3] = 0;
            triangles[i * 3 + 1] = i + 1;
            triangles[i * 3 + 2] = i + 2;
        }

        Vector2[] uvs = new Vector2[contourPoints.Count];
        for (int i = 0; i < uvs.Length; i++)
        {
            uvs[i] = new Vector2(vertices[i].x, vertices[i].y);
        }

        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.uv = uvs;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        
        }
    }
plain spire
#

Hi!

I have a level editor in my game, and i thought it'd be cool to add modding (sorta) where you can make your own level editor objects in unity, dump the prefab into some folder, and have the game get all prefabs in that folder and make them usable and placeable in-game

How can I do this? I've heard of StreamingAssets, but I'm not quite sure that's the right solution for this.

crisp flower
#

how do you make a TMP word invisble?This isn't working:

C#

    private void UpdateTextRatio()
    {
        // Calculate the number of visible words based on the ratio
        int totalWords = textMeshPro.textInfo.wordCount;
        int visibleWords = Mathf.RoundToInt(totalWords * visibleRatio);

        // Modify the alpha value of each character's vertex color to hide or reveal words
        for (int i = 0; i < textInfo.meshInfo.Length; i++)
        {
            TMP_MeshInfo meshInfo = textInfo.meshInfo[i];
            int characterCount = meshInfo.vertexCount / 4;

            for (int j = 0; j < characterCount; j++)
            {
                byte alpha = j < visibleWords ? (byte)255 : (byte)0;
                for (int k = 0; k < 4; k++)
                {
                    int vertexIndex = j * 4 + k;
                    Color32 color = meshInfo.colors32[vertexIndex];
                    color.a = alpha;
                    meshInfo.colors32[vertexIndex] = color;
                }
            }
        }

        // Update the vertex colors in the TextMeshPro component
        textMeshPro.UpdateVertexData(TMP_VertexDataUpdateFlags.All);
    }```
zinc plover
chilly surge
plain spire
#

theres also an editor

#

at the moment levels arent shared, theyre purely a single player thing

#

so its nice to be able to add your own prefabs into the mod folder to use

#

apparently StreamingAssets can do it?

tardy crypt
thick terrace
# plain spire apparently StreamingAssets *can* do it?

if you're loading data files in your own format, you can basically put them wherever you like if you give it the right path at runtime! StreamingAssets is there for assets you want to include in the unity project yourself but not import as asset database assets

knotty sun
plain spire
#

oh

plain spire
#

i dont quite have the flexibility to create my own format now as i am not that skilled

#

i was just wondering, is there a way to load a prefab from outside the game, into the game

crisp flower
plain spire
#

which im sure is possible

thick terrace
knotty sun
deft timber
#

and change alpha of that canvas group

plain spire
#

at least for early mods

#

hell, VRChat does that for avatars

zinc plover
plain spire
#

so its definitely not foreign to gamers, and if someone wants to mod a unity game i feel its expected to have to touch unity

cosmic rain
neon plank
#

I noticed that inside OnStateExit in StateMachineBehaviour any trigger which is used for the transition is already consumed... is there a way to know if it was consumed for the specific transition?

chilly surge
#

Having to have a Unity account and license, download a 10 GB Unity editor, know enough about Unity to work your way around things, sounds like a pretty high barrier to entry for people wanting to mod your game.

swift cobalt
thick terrace
cosmic rain
plain spire
thick terrace
plain spire
#

like i wanted to mod buckshot roulette, so i had to learn godot

#

not a ton, just enough to import a model and do basic coding

#

i suppose it is what it is, if you want to mod a game you need to learn the engine thats just how modding is

zinc plover
chilly surge
#

Sure, for people that are hardcore fans of your game, they will find their ways to mod it even if you have zero support for modding, but that's not really the point if you have the goal to make modding accessible to more people than those hardcore fans.

plain spire
#

im just making it easier by saying "yeah rather than decompiling the entire game, heres a folder you can add your unity prefabs into and itll put them in the editor for you"

thick terrace
plain spire
#

i suppose fair

#

at the end of the day this is just the easiest method that i can think of and the question kinda stays the same

thick terrace
#

yeah, what works best depends entirely on your game

plain spire
#

the level editor objects arent really complex anyway its just a model, the desired collision, and a script that says "hey yeah im a placeable object" which i can point people to

swift cobalt
plain spire
#

takes like 2 secs to add and i cant imagine its terribly hard to learn how to make a prefab from a beginners perspective

cosmic rain
knotty sun
plain spire
ashen yoke
#

plenty of methods that achieve this, asset bundles, harmony and so on

plain spire
#

im pretty sure asset bundles DO support scripts

#

would be real silly if they didnt

knotty sun
knotty sun
plain spire
#

by seeing it on the asset i assume

ashen yoke
#

typically they dont, the assembly is loaded and the main game uses reflection to look for base classes

#

all approaches are used, interfaces, attributes

#

every game does it differently but in general you inherit some base class game provided for extension

plain spire
#

yeah unity says they can be included in a assembly and loaded using mono reflection

thick terrace
#

if you want to put an existing script from the game on the assets in your bundle you don't need to do any of that, it's only if you want modders to be able to add brand new code that you need that

plain spire
#

yeah

#

thats fine for the moment then

#

as long as it supports prefabs and scripts that ive already written then its fine

ashen yoke
#

common approach i see is when dev provides an SDK for unity, so modder installs unity, adds the sdk package and it comes with scripts

plain spire
#

yeah

crisp flower
weary swift
#

Yo ! I want to implement AI pathfinding In my 3D game, I heard about the Unity's built-in Navmesh system, is this the common tool to use for this ? And is there other tools ?

weary swift
#

3D

knotty sun
#

then Unitys Ai.Naviagation is just fine

steady moat
weary swift
#

It's the one that cost like 60 bucks ?

knotty sun
#

there is a free version you can get from Github

weary swift
#

Thanks for the info

weary swift
#

And is there other common pathfinding principles other than navmesh ?

#

I don't know if principles is the right word, but like ideas

knotty sun
#

Really only A* as mentioned above

weary swift
#

Perfect then

knotty sun
#

there are other path finding algorithms but they are not really for the inexperienced or faint hearted

weary swift
#

Do you have some name right away, just for my culture pls

knotty sun
#

look on wikipedia

weary swift
#

Ok thanks !

fervent furnace
#

most of times you are not reducing the running time of your path finding but reducing the number of vertices

devout basin
#

Question: How to refer to a Json file dynamically?

My problem is that after building, the game doesnt work, i suspect it being the Json file not being reached. Right now its path is:

#

How do I make path work post build?

knotty sun
devout basin
#

Thats basicly the only time i use the path, the loadMissions method just collects the objects from the file using the set path

knotty sun
devout basin
#

The build yeh, doesn't work there, im a bit confused cuz im stressed. Deadline is nearing and somehow my project decided to merge its branches. ๐Ÿ˜…

#

How would it look?

mellow sigil
#

[SerializeField] private TextAsset missionsJson and drag the file there in the inspector, then loadMissions(missionsJson.text)

knotty sun
#

well go and search 'unity streamingassets'

devout basin
#

How to handle it now?

mellow sigil
#

Which technique did you use, TextAsset or streaming assets?

devout basin
#

I copypasted the oner you posted.

mellow sigil
#

Post the code as text, I can't modify a screenshot

devout basin
#
    private List<Mission> loadMissions(string path)
    {
        List<Mission> missions = new List<Mission>();
        // red the json file
        jsondata = File.ReadAllText(path);
        Debug.Log(jsondata);
        // Deserialize the json file
        List<JsonMission> jsonMissions = JsonConvert.DeserializeObject<List<JsonMission>>(jsondata);

        foreach (JsonMission mis in jsonMissions)
        {
            Mission mission = makeMission(mis.objective, mis.description);
            missions.Add(mission);

        }

        return missions;
    }
mellow sigil
#
private List<Mission> loadMissions(string jsondata)
{
    List<Mission> missions = new List<Mission>();
    Debug.Log(jsondata);

the rest is the same

shy citrus
#

Need help with github.

If I added a new unity package that contains over 100mb of files, how can I push it to the github repo?

knotty sun
devout basin
knotty sun
devout basin
knotty sun
devout basin
#

Holds like 8+ different missions, my teacher taught me to put such data in an external file

#

And not in the script

knotty sun
devout basin
#

Ooooh, first time doing it in unity, didn't know such a thing was made by Unity ๐Ÿ˜…

#

I gotta look into that though, sounds like i missed smth cool

knotty sun
#

basically just the same as you are doing, just 'the Unity way' of doing things

devout basin
#

Aaah i see.

lunar python
#

I just attach all player stats to player script for easy modification

devout basin
#

I apologise again for the hasty reponse and possible unfriendly behaviour. I was just stressed as deadline is pulling up and suddenly the build didn't want to work.

blissful grove
#

Can someone tell me why the leak detection always jumps back to "Enabled"? I set it to "Enabled With Stack Strace" and the console still tells me to turn it on:
A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details. Leak tracking may be enabled via `Unity.Collections.NativeLeakDetection.Mode` or from the editor preferences menu Edit > Preferences > Jobs > Leak Detection Level.

dusky lake
#

set it, save project, close the editor and open the project again

#

see if that helps, usually helps me when settings dont save ๐Ÿ˜„

#

oh nvm, didnt see the first line

blissful grove
#

did it multiple times and snapped back ๐Ÿ˜…

fervent furnace
#

if you didnt use any native collection, that probably google first to see if there are bugs in your editor version

blissful grove
#

I already assumed which script it was and turned out it is the one.

private NetworkList<byte> remainingTokens/* = new();*/;```
now I'm trying to figure out why I cannot initialize it as new ๐Ÿง
fervent furnace
#

constructor maybe private

hard viper
#

private constructor is weird

blissful grove
spice briar
#
void FixedUpdate(){
if (canSeePlayer)
{
    eyePos.forward = lastPositionPlayerSeen - transform.position;
    eyePos.localEulerAngles += curRecoilInaccuracy * transform.right;
    eyePos.localEulerAngles += Random.Range(-0.5f, 0.5f) * Vector3.up;

    if (timeSincePlayerSeen == 0)
    {
        //CooldownShot();
        ResetShot();
    }
    else if (roundsLeftInBurst <= 0)
    {
        onCooldown = true;
        Invoke(nameof(CooldownShot), cooldown);
        curRecoilInaccuracy = 0;


    }

    if (!onCooldown && canShoot && roundsLeftInBurst > 0 && timeSincePlayerSeen > reactionTime)
    {
        Instantiate(bulletPrefab, eyePos.position, eyePos.rotation);
        canShoot = false;
        roundsLeftInBurst -= 1;
        //Invoke(nameof(ResetShot), 50/650);
        curRecoilInaccuracy -= 0.1f;
        Invoke(nameof(ResetShot), 0.05f);
        anim.Play("Base Layer.Shoot");
    }
    else curRecoilInaccuracy += 0.025f;


    timeSincePlayerSeen += Time.fixedDeltaTime;
}
else timeSincePlayerSeen = 0;
}```
#
 void CooldownShot()
 {
     float distFromPlayer = (lastPositionPlayerSeen - transform.position).magnitude;
     distFromPlayer = Mathf.InverseLerp(0, 200, distFromPlayer);
     int maxShots = (int)Mathf.Lerp(1, 6, -distFromPlayer);
     Debug.Log(maxShots);
     roundsLeftInBurst = Random.Range(1, maxShots);
     onCooldown = false;
 }```
#

hey everyone, so im working on enemy FPS AI

#

basically i want the amount of shots in a burst to be lower if the player is further away. right now, the lerps work and the correct maxShots gets assigned, however it still shoots 6 bullets no matter what

#

shotsLeftInBurst is the correct value, but it still seems to shoot multiple shots no matter what.

dusky lake
spice briar
#

distFromPlayer is correct

#

already tested that

dusky lake
#

what values does it contain?

spice briar
#

lerp from 0-1 depending if its 0m - 200m from the player

#

and then that lerp sets the max amount shots the burst will contain

dusky lake
#

distFromPlayer = Mathf.InverseLerp(0, 200, distFromPlayer); this will contain 0-200 depending on what value distfromplayer had before

#

not 0-1

#

oh nvm

#

didnt see inverse

knotty sun
spice briar
#

the issue is with the if statement that actually shoots the bullet ( i think?)

#

as you can see the debug log is giving 1 as max shots

#

which is where it should be as he is >200m away

knotty sun
#

so it should be maxShots+1

spice briar
#

right, also found an issue in the lerp doing -distFromPlayer and not 1/distFromPlayer

#

hes still shooting many bullets though.;..

#

even more than 6 which should be the max possible

knotty sun
spice briar
#

what do you mean?

knotty sun
# spice briar what do you mean?

look at this

else if (roundsLeftInBurst <= 0)
    {
        onCooldown = true;
        Invoke(nameof(CooldownShot), cooldown);

runs every Fixed update, so once it is true the Invoke will happen untill the first one actually starts

spice briar
#

oh, while its waiting for the first invoke to finish its calling it every frame?

#

i see

knotty sun
#

yes

spice briar
#

so how would i fix that, just make it == ?

#

oh wait

knotty sun
spice briar
#

yeah yeah

#

ill try that

#

alright thats almost working, it does a large burst at the start and then correctly fires in single shots

#

fixed that, when timePlayerSeen is zero i just set the burst to 1

#

well if (timeSincePlayerSeen == 0) { onCooldown = true; CooldownShot(); //roundsLeftInBurst = 1; ResetShot(); }
this works a bit better as if the enemy is close it doesnt go 1 shot first

#

@knotty sun Thank you for the help

#

๐ŸคŽ

lapis badger
#

I'm currently following a tutorial video, and while everything so far works perfectly, I occasionally get the NullReferenceException: Object reference not set to an instance of an object error on launch. It seems completely random. No matter the wait between re-launching the game. Sometimes it happens, but usually doesn't. I have no idea what this could be. It apparently has to do with the input system, which looks like this:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameInput : MonoBehaviour {

    public event EventHandler OnInteractAction;

    private PlayerInputActions playerInputActions;

    private void Awake() {
        playerInputActions = new PlayerInputActions();
        playerInputActions.Player.Enable();

        playerInputActions.Player.Interact.performed += Interact_performed;
    }

    private void Interact_performed(UnityEngine.InputSystem.InputAction.CallbackContext obj) {
        OnInteractAction?.Invoke(this, EventArgs.Empty);
    }

    public Vector2 GetMovementVectorNormalized() {
        Vector2 inputVector = playerInputActions.Player.Move.ReadValue<Vector2>();

        inputVector = inputVector.normalized;

        return inputVector;
    }

}

Can anyone help me solve this issue?

knotty sun
#

screenshot the complete error and stack trace

lapis badger
#

I need to encounter it first, give me a moment

#

I don't know how it even happens

#

Just occasionally when I hit play, it pops up

#

I'll send a screenshot of the stack trace once it appears

lapis badger
#

what the hell

#

now it won't appear

knotty sun
#

actually no, it can only be Player.Interact is null

lapis badger
#

I still don't quite understand how this Interact works

knotty sun
#

that is not important for the error

lapis badger
#

just saying*

#

need any screenshot or code?

knotty sun
#

no as long as it is that line of code that is throwing the exception

lapis badger
#

I'd need to encounter the error to fully confirm via screenshot

#

ok, what about this

#

I will ping you with a screenshot when it happens, if it happens, and for now ignore my question, ok?

knotty sun
#

fine

lapis badger
#

then after the ping, once you have time, ping me back and we'll fix the issue

#

alright, see you later, possibly

knotty sun
#

or rather

private void Awake() {
        playerInputActions = new PlayerInputActions();
        playerInputActions.Player.Enable();
}
private void Start() {
        playerInputActions.Player.Interact.performed += Interact_performed;
    }
fallow rain
#

whenever I switch platform to "linux" or trying to build linux build via command line I have a crash related to burst (editor closes itself intstantly). host is windows.
when I untick "burst -> enable compilation" I can switch platforms without problems or errors.
where to start?

fallow rain
ashen yoke
#

there are bits and pieces of info that might help, i googled using (burst-llvm-16) burst_Intrinsic_unlikely crash

knotty sun
fallow rain
knotty sun
static matrix
#

how should i go about doing this
I have a creature that should be positioned on a wall, but i'd like for it to be able to sink into a wall and warp somewhere else where it pops out of a new wall
I could do this the slow way where I set up points on each room where it can emerge
but idk if theres a faster way I should do this

#

any reccos?

rigid island
static matrix
#

that should work, although i'd then have to get the orientation
how could I get a random point on a wall?

rigid island
#

You can get the normal of the wall then use that in your plane

#

or probably do something with collider

fading walrus
#

can someone help me with this error? i was adding playfab to my gorilla tag fangame

rigid island
#

!ide

tawny elkBOT
static matrix
#

well gee golly looks like there should be a comma somewhere

fading walrus
static matrix
fading walrus
#

i use visual studios

#

do you know the fix?

rigid island
fading walrus
#

Ok

rigid island
#

it will tell you exactly how to fix it

#

in the editor

fading walrus
#

ok

#

why is k blocked?

static matrix
#

1984

#

idk
too much spam?

fading walrus
rigid island
fading walrus
#

oh

static matrix
#

(facepalm gif)

waxen blade
#

I have a yield return new WaitForSeconds(4f) that refuses to advance.

I have a log checking the timescale to ensure it stays at 1f the whole time (which it does), I'm making sure the object and script do not get disabled so the WaitForSeconds does not get interrupted. However, if I change the WaitForSeconds to 1f, it DOES make it through. 2 or more seconds and it doesn't make it through.

What else can I look for that is preventing me from settings WaitForSeconds beyond 1f?

static matrix
#

idk much about coroutines you could try waitforsecondsrealtime

waxen blade
#

That could cause issues if someone's computer hangs up for a second. But I'll see if it works.

#

Same issue.

static matrix
#

okay idk then
not good with coroutines

rigid island
rigid island
waxen blade
static matrix
#

using several different tilemaps
each screen is its own tilemap

rigid island
#

oh its 2D ? thats even easier.

static matrix
#

oh I see what you mean
yes they all have common forward axis

rigid island
#

yeah 2D is easier to find random point on collider lol

#

3D was a bit difficult since you have so many faces

rigid island
naive swallow
rigid island
#

StartCoroutine in update ? lol

waxen blade
waxen blade
fading walrus
rigid island
naive swallow
fading walrus
naive swallow
fading walrus
#

i did Alt+enter

fading walrus
naive swallow
rigid island
fading walrus
#

ok

rigid island
fading walrus
rigid island
#

why is it there in the first place?

fading walrus
#

IDK

#

oops

#

cap locks

spring creek
fading walrus
rigid island
#

this isn't a guessing game, surely you must know why you are doing what you're doing

#

if you're new don't start by making a "gtag fangame "

#

make flappy bird or sum

static matrix
#

so how does one get a random point on a tilemap collider?

deft quest
#

Assistance with Root objects holding destroyed scripts (Scene swaping)

waxen blade
waxen blade
lapis badger
#

@knotty sun

static matrix
#

exo reportedly forgot to assign the object anywhere

#

(or it stopped existing at some point and you never checked)

knotty sun
lapis badger
static matrix
#

thehell is readvalue

naive swallow
# lapis badger

Either playerInpoutActions, playerInputActions.Player, or playerInputActions.Player.Move is null

#

(probably the first one)

knotty sun
#

actually it is probably Move

lapis badger
#

imma check where it's made

waxen blade
#

!code

tawny elkBOT
naive swallow
#

If it's missing a binding you get a different error than an NRE

#

it won't even compile at that point

lapis badger
#

only here

knotty sun
#

but he accesses the others earlier in his code without exceptions

static matrix
#

OHHH MY GOD IM SUCH AN IDIOT
i forgot to set the timer to stop flailing back to 0 ๐Ÿ’€
so after the first flail the arms wouldn't flail again

#

if I had a nickel for everytime I started a timer and forgot to set it back to 0 when it was done

naive swallow
# lapis badger only here

Hm, that's in Awake so that should definitely be running before GetMovementVectorNormalized, depending on how you're calling it. Try logging playerInputActions at the top of this function, and another one in Awake right after you set it. See which one prints first

lapis badger
#

where exactly?

#

I'm blind

#

here?

naive swallow
knotty sun
naive swallow
#

And make sure to put something else in there so you know which is which

#

like "Awake: "

knotty sun
lapis badger
#

oh yeah xd

naive swallow
# lapis badger here?

Yes. And then another one at the top of GetMovementVectorNormalized. See what order they print in

knotty sun
static matrix
#

a lot of new programmers in the chat today it seems
but maybe thats just me

knotty sun
#

must be school holidays

static matrix
#

ah

lapis badger
#

I'll test this

static matrix
#

makes sense

naive swallow
static matrix
#

based, project productivity on holiday

static matrix
lapis badger
#

yeah I should also shut up abt this

static matrix
#

great
javascript is hell
c# is great

lapis badger
#

(beginning)

static matrix
#

well javascript isn't that bad
its better than the htmlcss part

lapis badger
naive swallow
# lapis badger (beginning)

Okay, I don't see any problems with this but I also don't see the null reference exception you said you were getting

knotty sun
lapis badger
#

this happens randomly

waxen blade
lapis badger
#

for no apparent reason

#

and no rhythm

#

there's like a small chance this appears on launch

naive swallow
lapis badger
#

it's always the same

naive swallow
lapis badger
#

so try to get it again?

naive swallow
#

I mean see what the logs you just added say when the error occurs

knotty sun
lapis badger
#

line?

naive swallow
lapis badger
#

the problem is I triple checked and it's exactly as in the tutorial

naive swallow
#

It's the C# half of the new input system asset

naive swallow
#

You're not meant to edit it by hand

lapis badger
#

happens like once an hour and it's enough to re-run to make it disappear

#

it's just scary

naive swallow
# knotty sun one for you digi

No, I'm actually pretty sure in this case this code is correct. My hunch is that something externally is calling GetMovementVectorNormalized on a prefab or deactivated object that hasn't run Awake yet

rigid island
#

why are you editing a c# generated class

lapis badger
#

if this shit happens in serious projects it might not be so easy

naive swallow
rigid island
#

Ohh myb then

naive swallow
knotty sun
naive swallow
#

If you could share the !code of those, we can see if anything might be calling it on a disabled object

tawny elkBOT
naive swallow
# lapis badger

Okay, so, you've got a few of those in the same class. Show the !code for Player.cs

tawny elkBOT
lapis badger
#

alright, but keep in mind this is in the middle of a tutorial segment, so stuff might not make sense like the duped text chunk

#

shit

naive swallow
#

Use a bin

lapis badger
#

a what

waxen blade
#

For my WaitForSeconds issue, I found a workaround. It doesn't explain why the wait stops, but instead of waiting the full 4 seconds, I wait 1 second, and then I start another Coroutine that waits the remaining 3 seconds and then proceeds on with the rest of the code. When I daisy-chain it to the second coroutine, the second coroutine does not get interrupted like the first one does.

naive swallow
lapis badger
#

hastebin or hatebin

naive swallow
#

it literally does not matter just pick one from the bot and post it

twilit shoal
#

Hello! I have a question related to scriptable objects! Are scriptable objects conidered as persistent data in a build?

naive swallow
naive swallow
tawny elkBOT
twilit shoal
#

or sould i just create an external JSOn save file ?

naive swallow
twilit shoal
naive swallow
# twilit shoal oh, so only for as long as the game will run. if for example, during the game th...

So, let's imagine you had a ScriptableObject PlayerStats that has an HP value of 100.
If you had code that changed that instance's HP in game, they'd behave differently:

  • In a build, your HP would persist across all scenes and loads, but would reset to 100 when you close the game.
  • In the editor, your HP would persist across all scenes and loads, but when you exit play mode, the HP would remain at whatever it was when you closed it
frosty surge
#

Hi, i have a small problem here.
I am instantiating a prefab and parenting it into a parent, the issue is that when i scale down the parent the prefab becomes bigger, i tried to change the wordPositionStays to false it worked but the prefab doesnt spawn exactly at the parent location...
Any help?

twilit shoal
#

i have the system work with player prefs, but i know those are saved in registry and not used for saving data

edgy stump
#

Why it's returning null audio clip and it's not playing, but when I select the clip, and start playing It, it's playing. Why this happening?
Script: https://hastebin.com/share/yukisejako.csharp

terse turtle
#

How can I make a simple lock room system with Tilemap 2D? I want the doors(Blocked area) to be blocking the Player from entering the next room until they have completed the objective of killing all enemies in that room. How would an individual go about adding this?

rigid island
dusk apex
# naive swallow So, let's imagine you had a ScriptableObject `PlayerStats` that has an HP value ...

To add to that: if a reference to the specific instance of the scriptable object is ever lost (for example on loading a new scene where there isn't a persistent object referencing the modified SO), the references to the SO in the new scene will be that of the non-modified default SO.

in order to have your mutated instance of an asset (scriptable object asset) to be the same in all the scenes, you should provide a reference to that asset in every single scene.
https://discussions.unity.com/t/scriptable-object-resets-randomly-between-scenes/207798/5 @twilit shoal

terse turtle
rigid island
#

its a key-value pair system

#

you search a value by a "key"

#

Imo you can just use a Prefab and make this easier with Tilemap gameobject brush

dusk apex
terse turtle
twilit shoal
terse turtle
dusk apex
rigid island
terse turtle
rigid island
swift cobalt
#

I have a strange issue. I got this class

public class HTTPCommunication
    {

        public  Action<string> OnHTTPSuccess;
        public  Action<string> OnHTTPError;

        string uri;
        

        public HTTPCommunication(string uri)
        {
            this.uri = uri;            
        }
...

and when I am trying to subscrible to the event from another script

void OnEnable()
    {
        httpCommunication = new HTTPCommunication(URI);
        httpCommunication.OnHTTPSuccess += OnHTTPObjectRecieved ;

I am getting the error TTPCommunication' does not contain a definition for 'OnHTTPSuccess. Any idea ?

swift cobalt
rigid island
swift cobalt
dusk apex
rigid island
swift cobalt
terse turtle
rigid island
dusk apex
# edgy stump No errors

Not sure. Try logging the path and verifying that it's correct. Ensure the inspector you're looking at is the correct object instance that's been changed. Ensure the audio source is the expected object in scene etc

terse turtle
rigid island
frosty surge
loud patrol
#

New to Unity, and ran into an issue.
I have a Canvas with a couple buttons (A, B, C). When you click A, it Instantiates a B button from a prefab. If you click C it deletes B buttons. However, when I try using Destroy(go.gameObject), the object is removed from the scene, but the button image stays on screen.
Any help is greatly appreciated. And I can give examples, or more context if needed.

naive swallow
dusk apex
knotty sun
edgy stump
loud patrol
knotty sun
tawny elkBOT
dusk apex
deft quest
#

I made a thread, is there anyone who can help me with my issue?

loud patrol
edgy stump
#

Like this?

#

Well, previously FMOD installed in project

dusk apex
knotty sun
loud patrol
dusk apex
#

If you see it then it's in the scene unless your camera is malfunctioning

dusk apex
#

How to properly post !code (the large code block section)

tawny elkBOT
lavish laurel
#

thats what I did

#
// Your code here

Add a comment with a line number if there is an error message.

dusk apex
#

Don't skip

lavish laurel
#

I meah yeah but which one

#

Hello, I'd like help with my code. I can't figure out why the high-score table isn't updating or displaying information. Does anyone know how I can fix/do this?

The first image has information but is on game-screen before I load game. Second image is what happens when game loads

Here is the link to my code https://hatebin.com/qblkmshzgk

leaden ice
#

Also instead of that manual bubble sort you're doing why not just highScoreEntryList.Sort(e => -e.score);?

lavish laurel
leaden ice
#

I'd say it's probably this though:
entryTemplate.gameObject.SetActive(false);

lavish laurel
#

Thats not assumption, it's changing but I'll add some

leaden ice
#

you're deactivating the template

#

so the instances are also not activated

#

oh you are activated them in the other function though.
Well - Debug.Log time

lavish laurel
dusk apex
#

Else this is an XY problem where you're assuming it's to do with code or a specific object. Where what you're not wanting to see in the scene may have nothing to do with the buttons you're managing/destroying.

leaden ice
dusk apex
#

Assuming this isn't an editor script where the dirty canvas may not be updating itself, you ought to be able to see the object in the scene and game window if it still actually exists.

leaden ice
#

yes check the hierarchy

lavish laurel
loud patrol
# dusk apex Rather than look at code, you need to verify which objects are still persistent ...

Could you give some more specific guidance on this? The contents of my hierarchy shows a camera, the canvas containing to two buttons (create, and destroy ones), an event system, and my button manager object. When I click the create button a new button is created in the hierarchy, and when I click the destroy button that same button is removed from the hierarchy.
I'm also not sure what you mean by "editor script". I tried running Canvas.ForceUpdateCanvases after removing the button but no success.

dusk apex
#

Can you show an image of the hierarchy, scene view and game view?

#

Before and after destruction of the buttons

#

Assuming you aren't doing full screen mode, you ought to be able to encapsulate the three in a single image each.

loud patrol
dusk apex
#

You'd post it here if it's necessary to illustrate to others what's occurring that should not be occurring.

loud patrol
#

first is base state, second is after adding the button, third is after removing the button

dusk apex
#

So in the scene view, the cloned object has been removed.

#

This implies, the code works and that the object was successfully created and destroyed. The new concern would be to look up why the canvas wasn't properly repainted.

#

Googling will probably yield some good results

loud patrol
dusk apex
loud patrol
edgy stump
#

it's load type

#

by default it's set to decompress on load

#

so, I need to fix it

#

but I idk how to fix โ˜ ๏ธ

peak cobalt
#

does anyone know how to write a script that would randomly swap the location of 3 identical gameobjects when a button is clicked?

rigid island
#

as this is very basic stuff

hardy mulch
#

Anyone have an implementation for Mathf.HalfToFloat (and Mathf.FloatToHalf)? I need to do some conversions outside of the unity context and thus don't have access to Mathf

I attempted to implement like this:

        public static ushort FloatToHalf(float val)
        {
            return (ushort)(Half)(val);
        }

        public static float HalfToFloat(ushort val)
        {
            return (float)(Half)(val);
        }

However am getting different results than what unity provides

knotty sun
hardy mulch
#

The half class contains explicit operater overloads for it, but seem to be doing something different than unity

dusk apex
# loud patrol Ok. I'll have to dig into it later. I appreciate your time and patience very mu...

Having the buttons persist an extra frame likely isn't favorable as who knows what the user could be doing with the buttons before the culling. It may be appropriate to repaint the very next frame instead (repainting has some expense but you're working with ui so it probably isn't going to be very time sensitive). Invoke might be appropriate in this casecs Invoke("Canvas.ForceUpdateCanvases", 0.001f);(haven't tested the code but it should be valid)

knotty sun
hardy mulch
#

Right, but that doesn't help me lol. Im asking specifically the algo for the unity impl

knotty sun
simple egret
#

Unity's implementation is not visible as it's made on the C++ side of the engine.

hardy mulch
#

Yeah im just hoping someone has worked out how its implemented

hardy mulch
knotty sun
hardy mulch
#

Right now I need to go from a ushort to a float. Directly casting them does not work, casting to a Half does not work, so I don't know what would work

knotty sun
#

define does not work. Casting from ushort to float will give you the same value as well as it can be expressed as a float

hardy mulch
#

In unity Mathf.HalfToFloat(20604); returns 35.875
Every variation iv tried in my own project has given a different number

#

For instance, this implementation:

public static float HalfToFloat(ushort val)
{
    return (float)(val);
}

returns 20604

simple egret
#

ushort and Half are not the same types.

#

One stores an integer number, the other a floating point number

hardy mulch
#

Im aware, but they're the same size and what unity uses for them. The unity method is public static extern float HalfToFloat(ushort val);

#

And under the hood C# implements half's with ushorts anyways

late lion
fervent furnace
#

i think the ushort is actually bit respresentation of the half

hardy mulch
fervent furnace
#

so directly casting not work, google and copy other code by yourself

knotty sun
#

so this is the same as int and float

late lion
hardy mulch
#

Oh, the different impls iv attempted have all been around the same ballpark of extremely high numbers

simple egret
#

So it's just reinterpreting the bits, not converting anything

late lion
#

Of course the ushort is going to be a completely different number from the float it was converted from. It's a completely different representation of numbers.

hardy mulch
knotty sun
hardy mulch
#

The C# side? Iv poked around the Half struct a bit

knotty sun
#

so show me

hardy mulch
#

What?

knotty sun
#

the Half struct

late lion
hardy mulch
#

Because im getting different numbers lol

#

Or im using it wrong

fervent furnace
#

Just extract the sign and exponent and mantissa by yourself

hardy mulch
#

I don't know much about how the cast overloading works, I thought

public static float HalfToFloat(ushort val)
{
    return (float)(Half)(val);
}

would give me what I wanted but its not

simple egret
#

Yep that's a pure reinterpretation. Unsafe.As<TFrom, TTo>(ref TFrom) (.NET 5+) does that

knotty sun
#

yes you are using it wrong, what you are doing is like taking a float, treating it like an int because they are the same length then converting that as an integer

knotty sun
fervent furnace
#

Ah
Half h=*(Half*)&ushort

simple egret
#

You basically need to extract the bits as they're laid out in memory, and apply them to the other type

hardy mulch
#

As so I need to actually litterly map bits, without trying to convert anything

#

So HalfToFloat is implemented as a nop in unity lol

knotty sun
#

yes, exactly the same as a float or a double

simple egret
#

Yep, using pointers may be an option. The C++ side probably just takes a pointer type and casts it to another pointer type

late lion
tardy crypt
#

can't you just apply bitmasks with bitwise operations?

hardy mulch
fervent furnace
#

Just cast it by pointer

hardy mulch
#

And to make code consistant between unity and my own project

knotty sun
# hardy mulch And to make code consistant between unity and my own project

In computing, half precision (sometimes called FP16 or float16) is a binary floating-point computer number format that occupies 16 bits (two bytes in modern computers) in computer memory. It is intended for storage of floating-point values in applications where higher precision is not essential, in particular image processing and neural networks...

simple egret
hardy mulch
#

But now that I understand that (thanks SPR2) iv got it working

simple egret
#

If you're able to toggle unsafe code on, then do what the C++ probably does, using pointers:
Half target = *(Half*)&source_ushort;

hardy mulch
#

Yeah unsafe is enabled in this project, I implemented like that

#
public static unsafe float HalfToFloat(ushort val)
{
    Half h = *(Half*)&val;
    return (float)h;
}
tardy crypt
#

what's all this stuff?

simple egret
#

.NET 7 and above unfortunately (see "Applies To" section at the bottom of the page)

#

Those use static abstracts in interfaces, pretty neat stuff, but too new for Unity to have it

tardy crypt
#

oh

#

i thought... unity supported c# 9??

knotty sun
tardy crypt
#

oh .net 7...

#

derp

#

nvm me then...

#

so wait they're up to like... .net9 and unity only uses .net 2.1?

simple egret
#

Yep, it's another branch entirely. Unity either uses ".NET Framework 4.x" or ".NET Standard 2.1".
Framework hasn't seen new versions in quite some time

knotty sun
simple egret
#

Both have been superseded by ".NET Core" which was rebranded to just ".NET" since it's the only one in development rn

tardy crypt
#

what are the major challenges to updating the .net version they use? is it that they have to update their "C++ side backend" or whatever? il2cpp? both? and some other stuff?

#

i have no idea how this all works, clearly...

#

does unity have its own implementation of the runtime or something?

simple egret
#

It uses Mono or IL2CPP yep

knotty sun
warm blaze
#

Could someone help me? Running into what I think is a unity editor bug.

Basically, I have public arrays that I have put values into, but when I try to pull a value from that array at start, I get a null reference exception. However, when that same function runs while the game is active, it works fine. It was also working fine before I had an issue that caused unity to crash.

somber nacelle
knotty sun
# tardy crypt hmm... interesting

It shouldn't be a major problem to migrate, other smaller engines have done it without major problems but it does require a lot of testing and, as we all know, Unity does not test shit nowadays

tardy crypt
#

interesting... ok i'll have to check it out

tardy crypt
#

i think yuou're going to have to show your code at least

warm blaze
#

Here is the inspector with the public array, the nullreferenceexception and the code that is causing it

tardy crypt
#

can you show line numbers?

tawny elkBOT
knotty sun
#

did you not read the bot message?

#

AI generated code, forget it

warm blaze
tardy crypt
#

check whether gamestate_script is null

#

you're getting the component but that could be null

#

unfortunately nullreferenceexception is not more specific than which line

warm blaze
tardy crypt
#

also line 56 refers to NumberOfWaves

lean sail
tardy crypt
#

you showed length of day

spring creek
tardy crypt
#

it's almost certainly not a bug in the editor

lean sail
#

I feel like a lot we discussed the other day was missed ๐Ÿ˜…. You shouldnt be declaring wave1, wave2, wave3 as fields like this

warm blaze
#

Fixed it by moving the script initializers into Awake instead of Start

spring creek
warm blaze
lean sail
warm blaze
lean sail
lean sail
warm blaze
spring creek
#

But yeah, in this case they mean multiple instances of the same class, which I could see feeling new

waxen blade
#

I believe I'm having a snythax issue. I have a GameObject called MainController that has a component called LevelController. LevelController has an IEnumerator method I'm trying to call. Since the component is already on the same GameObject I'm trying to call the IEnumerator from, I don't understand what reference is needed.

lean sail
#

This magic right here gives you the instance

waxen blade
#
                    LevelController levelController = transform.GetComponent<LevelController>();
                    levelController.StartCoroutine(LevelController.CompleteLevel());

I'm still not understanding the magic.

#

So I'm calling it like it's static

#

But I need to call it like it's not static.

lean sail
#

Static means its associated with the type, the type being LevelController. Your instance is stored in levelController

spring creek
waxen blade
#
                    LevelController levelController = transform.GetComponent<LevelController>();
                    levelController.StartCoroutine(levelController.CompleteLevel());
#

I think that was it. Am I able to do this in one line?

lean sail
#

Of course, but why would u want to

#

You need to store the levelController, so a one line solution would just make you call GetComponent twice

naive swallow
lean sail
#

You could turn this into a 1 line solution actually by making a public method in the level controller which starts the coroutine.

#

I tend to do this instead, I'm not a fan of other objects starting coroutines

rapid stump
#
    private void OnDoubleClick(PointerEventData eventData)
    {
        RectTransform mapPanelRect = mapPanel.GetComponent<RectTransform>();
        Vector2 localPoint;
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(mapPanelRect, eventData.position, miniMapCamera, out localPoint))
        {
            MapController.instance.SetDestinationMarker(mapPanel.transform.TransformVector(localPoint));
            Debug.Log($"MiniMapController: OnDoubleClick: evenData.position {eventData.position}" +
                $"\nlocalPoint {localPoint}");
        }
    }

Im completely lost at this point. I don't know what I'm doing wrong.
I've even tried calculating the new position myself and ofc that doesn't work XD

I'm trying to implement a minimap with an orthographic world space camera and a 10,000x10,000 canvas group. But I can't figure out how to calculate for the local position of the players click relative to the canvas group, when the player clicks on a raw image that is displaying the minimap camera. I'm using if (RectTransformUtility.ScreenPointToLocalPointInRectangle(mapPanelRect, eventData.position, miniMapCamera, out localPoint)) which works better than any other method I've tried, but it's still inaccurate, as you can see in the video

waxen blade
#

Got it. Okay, thank you.

warm blaze
#

@lean sail On the data for Days, would creating a Prefab for a "DayController" with a script that initializes all the parameters from an XML file or something like that be a good way to set it up?

I would instantiate it at start, and each day that goes by, delete it and instantiate a new object with the next day's info

spring creek
vapid lynx
#

Im making grass for my procedural terrain

#

andi created grass material using a shader

#

and then

#
{
    float[,] treeNoise = Noise.GenerateTrees(size, size, 0.5f);
    int treeCount = 0;
    int treeCount2 = 0;
    float worldX = 0;
    float worldZ = 0;
    float heightMesh = 0;
    Vector3 meshPosition = mesh.transform.position;
    for (int y = 0; y < size; y++)
    {
        for (int x = 0; x < size; x++)
        {
            float rngGrass = UnityEngine.Random.Range(0f, 0.5f);
            worldX = meshPosition.x + x;
            worldZ = meshPosition.z + y;

            RaycastHit hit;

            if (treeNoise[x, y] < rngGrass)
            {
                //  if (Physics.Raycast(new Vector3(worldX, 100, worldZ), -Vector3.up, out hit))
                //{
                //  if (hit.collider.name == "Terrain Chunk" && (100 - hit.distance) > 5)
                {
                    //    heightMesh = 100 - hit.distance;
                    GameObject grass = Instantiate(grassPrefab, new Vector3(worldX, heightMap[x, y], worldZ), Quaternion.identity);
                    grass.transform.parent = grassChunk.transform;
                    // }
                    // }
                }
                // xCoord += treePrefab.GetComponent<MeshRenderer>().bounds.size.x;
            }
            // zCoord += treePrefab.GetComponent<MeshRenderer>().bounds.size.z;
        }

    }```

use this code to create instances
#

howver it runs really slow so is there a better way of doing this?

spring creek
vapid lynx
#

wait im sorry

#

lemme delete it

#
        {
            float[,] treeNoise = Noise.GenerateTrees(size, size, 0.5f);
            float worldX = 0;
            float worldZ = 0;
            Vector3 meshPosition = mesh.transform.position;
            for (int y = 0; y < size; y++)
            {
                for (int x = 0; x < size; x++)
                {
                    float rngGrass = UnityEngine.Random.Range(0f, 0.5f);
                    worldX = meshPosition.x + x;
                    worldZ = meshPosition.z + y;

                    RaycastHit hit;

                    if (treeNoise[x, y] < rngGrass)
                    {
                        GameObject grass = Instantiate(grassPrefab, new Vector3(worldX, heightMap[x, y], worldZ), Quaternion.identity);
                        grass.transform.parent = grassChunk.transform;
                        
                    }
                }

            }
        }```
lean sail
# warm blaze <@119616167894712320> On the data for Days, would creating a Prefab for a "DayCo...

This is fully up to you if you want to do it like this. It makes some things easier like if it already exists. I think it is not a good idea, because once you start trying to add references to in game objects it gets funky. You'll start to have to reference every single thing via ID or some other lookup. And when you delete a prefab or anything, this wont be reflected in the file, something will just break later.

#

But then again, when talking about save systems for user progress it is the same issue. Where things must be saved via ID. But at this point the game is already made

dusk apex
latent latch
# rapid stump ```cpp private void OnDoubleClick(PointerEventData eventData) { ...

I gave some ideas yesterday about this if you were checking but ultimately what you need to do is keep track of the pivot on the minimap relative to your larger map, then get the local position on the phone map and add that to the pivot's location on the main map. I suggest remove the scaling at the moment and try to get that to work as scaling will require some more logic to get the correct units.

vapid lynx
#

so it only spawns in a radius around you

dusk apex
vapid lynx
warm blaze
mild osprey
lean sail
#

Especially since this seems like data you just need to read

rapid stump
# mild osprey I want to make sure I'm understanding the issue correctly. The issue your having...

My issue is that the calculation I'm using isn't accurate. It seems when the orthographic camera size is at 300, the localPoint fed into the destinationMarker setter is like 50X and 100Y higher than where the player clicked relative to the minimap canvas.
And the deviation grows as the orthogaphic camera size grows. So when the size if 1200, the deviation is like 100X 400Y from where the player clicked.
I did some testing, but it's not perfect ofc.
MM Camera Pos: -101.0505, 49.52332
Size: 300
EvenData Pos:775.24,1032.57
localPoint: 21.28, 208.44
NeedPos: ~ 0, 110

MM Camera POs: 10.37952, 123.8092
Size: 1200
EventData Pos: 535.05, 950.86
localPoint: 72.69, 614.22
NeededPos: ~ 0, 250

This is what I got from the test. The NeededPos is the rough local position relative to my minimap canvas that the destination SHOULD have been. But as you can see, the localPoint, what was fed into the destinationSetter isn't correct

warm blaze
mild osprey
rapid stump
# mild osprey Could you show the SetDestinationMarker method, I think I have an idea of what m...
    public void SetDestinationMarker(Vector2 Pos)
    {
        destinationPositionBool = 1;
        destinationPosition = Pos;
        destinationMarker.gameObject.SetActive(true);
        // Set the destination marker's position
        destinationMarker.transform.localPosition = destinationPosition;

        // Start moving the ship towards the destination
        isMoving = true;

        // Update travel time text
        UpdateTravelTime();
    }

It sets the localPosition of the destinationMarker (UI image) to the inputted position.

#

Should it not be the local position?

vestal arch
#

are parts of a coroutine that are before a yield return executed synchronously?

simple egret
#

All of it is executed synchronously

#

It pauses at the yields, and the engine resumes execution itself.
Coroutines do not run on another thread

rigid island
simple egret
#

Not even

vestal arch
#

i am extremely confused by these answers

rigid island
#

well *the Unity Way

#

its not true async

simple egret
#

No other code runs when code in a coroutine runs

vestal arch
#

so, it's like js async

simple egret
#

No

#

JS async is like C#'s async/await

vestal arch
#

does c# not use multiple threads for that

rigid island
vestal arch
#

but like, execution can jump between the coroutine and other code (Update or whatever), correct?

simple egret
vestal arch
#

so Unity is single-threaded?

rigid island
#

yeah many UI frameworks want you to run stuff on main thread

vestal arch
#

....so it's like js async

#

the underlying bits, not the interface

rigid island
#

Unity has Jobs now

#

well for a while

#

you can run multithreaded code

simple egret
vestal arch
#

yeah that sounds like js async

latent latch
#

well, c++ side of things it's more managed, but developer side you're dealing with linear execution orderings

soft shard
rigid island
vestal arch
#

anyways i think i phrased my question in a way that doesn't actually give an answer to what i was initially curious about. as i was trying to phrase a better question i realized i could just test it myself

latent latch
#

unity's methods usually have some sort of optimization going on, much like their physics and rendering, so it's not totally single threaded

simple egret
soft shard
#

Ah

waxen blade
#

I'm having another issue with calling coroutines. I have an object called **MainController **that has a **LevelController **component. That component contains a Coroutine, public IEnumerator StartLevel(). This time I am trying to call that method from an outside script, EnemyInfoMenuKeyboard.

On EnemyInfoMenuKeyboard, which is my outside script, I've tried calling the Coroutine with the LevelController component, as well as the MainController GameObject directly, but each gives me a null exception. I don't understand why it's a null exception because I have the MainController and LevelController added as public fields to my outside script, and when I debug I can see that levelController and levelController2 in the screenshot both contain data.

I tried the code for levelController and levelController2 separately, both result in null exceptions.

vestal arch
#

thanks for the insights though

#

my question was more about how yield return worked than how unity handled the coroutine

#

i just phrased it too broadly

simple egret
latent latch
vestal arch
rigid island
soft shard
chilly surge
waxen blade
#

Yeah, I've always been using that for code blocks, but didn't know there was a variation for in-line.

vestal arch
vestal arch
simple egret
# vestal arch my question was more about how `yield return` worked than how unity handled the ...

Unity just hijacks C#'s iterator methods feature, which allows you to call a method multiple times, and you'll get different values:

IEnumerator Sample()
{
    yield return 1;
    yield return 2;
    yield return 3;
}

// ...
Sample(); // -> 1
Sample(); // -> 2
Sample(); // -> 3
Sample(); // -> null

Unity executes the function internally, and retrieves the value you returned (eg. a new WaitForSeconds()) to decide when to resume (execute the function again) later on.

vestal arch
#

so if you yield return null in the coroutine, that effectively ends it?

simple egret
#

No, that tells Unity to wait one frame before resuming it

#

yield break; stops it completely

waxen blade
vestal arch
vestal arch
waxen blade
#

Right when I'm trying to call the coroutine from it.

vestal arch
#

right, which variable

#

i don't know what line 115 is from the screenshot

waxen blade
#

the result is the same from both 115 and 118.

simple egret
# vestal arch how does it differentiate the end of the coroutine from that?

It's complicated. Iterators actually compile into a whole class containing a state machine, a set of variables that say "what's my current state" and a function that moves to the next state.
Hitting a yield break advances the current state past the last state immediately, so when Unity executes the function again, it asks "is there any more states" to which the state machine answers "no", and the whole thing ends.

vestal arch
waxen blade
# vestal arch that doesn't answer my question

levelController.StartCoroutine(levelController.StartLevel()); levelController2.StartCoroutine(levelController2.StartLevel());

Both cause a null point exception regardless of which one I try.

vestal arch
chilly surge
vestal arch
waxen blade
#

I drag and dropped it in the editor

chilly surge
#

When you do yield break that essentially means "the next .MoveNext() should return false."
When you do yield return xyz that means "the next .MoveNext() should return true, and then .Current should return xyz."

vestal arch
chilly surge
#

It's exactly like JS generator yeah.

vestal arch
#

(that's about as much as i know about generators)

vestal arch
simple egret
#

Yep the IEnumerator method gets expanded into that state machine class with the Current and MoveNext()

mild osprey
# rapid stump ```cpp public void SetDestinationMarker(Vector2 Pos) { destinati...

How I would approach this issue is pretty close to what you were doing, there's just a couple other things I would account for. I think you're only going to want to keep track of double clicks that actually happen on the minimap, instead of what appears to be the entire panel. Second, there doesn't seem to be a reliable way of accounting for either camera movement or scale, which I think is the cause of your issue with scaling.
Here's what I would try:

//This should equal the x and y values of the camera's position when the app starts
Vector3 cameraStartPos = new Vector3(Camera.transform.position.x, Camera.transform.position.y, 0);

//Calculate the offset of the camera by finding the difference between the start position and the current position
Vector3 cameraOffset = cameraStartPos - Camera.transform;

//This is just to account for the initial scale of your minimap/camera zoom
float canvasStartScale = (initial size of canvas);

//This finds how zoomed in/out you are relative to the initial zoom
float canvasOffset = (current canvas size) / canvasStartScale

private void OnDoubleClick(PointerEventData eventData)
    {
        //Get the RectTransform of the Minimap instead of the whole map panel
        RectTransform newMapRect = newMap.GetComponent<RectTransform>();
        Vector2 localPoint;
        //Pass in the Minimap as well as variables to accurately find where the marker should be placed
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(newMapRect, eventData.position, miniMapCamera, out localPoint))
        {
            MapController.instance.SetDestinationMarker((localPoint + cameraOffset) * canvasOffset);
        }
    }

Obviously, this isn't a complete drag and drop solution, but I explain my logic with the comments. If this doesn't work, try replacing "destinationMarker.transform.localPosition = destinationPosition;"
with
destinationMarker.transform.position = destinationPosition;

vestal arch
simple egret
#

Yep, Unity does that on its own

vestal arch
#

cool, i was a bit confused from the syntax you used

chilly surge
#

You don't need to do that either

#

foreach essentially handles calling MoveNext/Current for you.

vestal arch
#

right, i mean from manual calls from SPR's snippet

simple egret
#

Unity gets it when you do StartCoroutine() and pass the coroutine, and it handles the rest

chilly surge
#

It's just like how for..of loops handles generators in JS.

vestal arch
simple egret
#

But indeed, foreach loops are expanded to a while loop that executes MoveNext(), but you don't see it since it's done at compile time

waxen blade
#

The weird thing is I can trigger the Coroutine easily directly from the MainController with this:

                    LevelController levelController = transform.GetComponent<LevelController>();
                    levelController.StartCoroutine(levelController.StartLevel());

But if I try to grab it the same way from the outside script, I get the null exception:

                            LevelController levelController2 = mainController.GetComponent<LevelController>();
                            levelController2.StartCoroutine(levelController2.StartLevel());
vestal arch
#

sidenote, for the first snippet you can use GetComponent<T>() directly, you don't have to go through the transform

#

im not super experienced with unity so this might not be useful, but have you tried logging it out in Start()/Update() and see if it's consistently null?

waxen blade
simple egret
#

Maybe the exception occurs in StartLevel()? Can you post the full error, it contains a stack trace which indicates where exactly in the code the exception occurred

waxen blade
#

`levelController.StartCoroutine(levelController.StartLevel());

This line works. I stepped one line at a time, and there's a Coroutine within StartLevel that is causing a null exception. But the exception got reported in the wrong script.

#

So looks like I was misled, and I misled you guys.

#

But now I can actually proceed from here. Thanks for your help.

simple egret
# waxen blade `levelController.StartCoroutine(levelController.StartLevel()); This line works....

Unless it's a very specific Unity bug (which isn't the case here), exceptions are never reported in the wrong place.
Perhaps the stack trace had a weird line that looked like this

LevelController.StartLevel()+MoveNext() (at ...LevelController:42)

Which indicates the issue happened in a coroutine, but the file + line number (at the end of the line, here LevelController line 42) should still be correct

#

(The class name and function name might be even more garbled than this due to how coroutines are made)

waxen blade
simple egret
#

Yep, you'll have 3+ lines in the stack trace (sample I just made up):

NullReferenceException: yadda yadda
  Sample.CoroutineB()+MoveNext() (at Assets/Scripts/Sample.cs:69) // exception here
  Sample.CoroutineA()+MoveNext() (at Assets/Scripts/Sample.cs:42) // called from there
  MonoBehaviour.StartCoroutine() (at Assets/Scripts/Sample.cs:10) // internal to Unity
  Sample.Start() (at Assets/Scripts/Sample.cs) // Coroutine A started in 'void Start()'
#

Most recent call first, meaning you read the stack trace top-to-bottom to go from the most precise location to the less precise ones

#

"exception occurred in coroutine B, on line 69 ; which was called from coroutine A, on line 42 ; which was called from Start, on line 10"

vestal arch
#

ok so it doesn't work for CustomYieldInstructions

upper pilot
#

I want to return a number in range based on another range, but with specific rules.

I have a game clock as a float 0f to 24f
When I pass a value 0.3f(not a clock value) I want to change it between 0f and 0.3 based on the time in game clock.

Example: GetValue(0.3f); => If time is 0f then value is 0, if time is 12f then value is 0.3f, if time is 18f then value is 0.15f

#

So the value will go from 0f to 0.3f then back to 0f based on the time.

#

0f->12f clock => 0f-0.3f value
12f->24f clock => 0.3f-0f value

#

My actual use case will be to separate clock into 4 parts, 6 hours each.
Then getting the value based on which time "zone" we are in.
Night, Morning, Afternoon, Evening basically

#

During Night value will go between 0f and 0.3f, Morning it will be 0f, Afternoon it will be 0f, Evening it will go from 3f to 0f etc.

#

I probably need a Lerp, but for my use case I might need 2 lerps?

vestal arch
#

nah just 1 would be enough

#

could do something like Lerp(min, max, 1 - Abs(time % cyclelength - firstpeak) / cyclelength)

simple egret
#

The most versatile way to do this would be with an AnimationCurve, on the X axis the clock time (0-24) and on the Y axis the value to output. Then you .Evaluate(clockTime) to get the value.
Especially useful if you want to change the ranges a lot depending on the time frames

upper pilot
#

It has to work based on various rules I set later.
Its not set in stone to work the way I mentioned earlier

#

So the 0f to 0.3 might happen in the Morning time for some cases

#

I guess we would swap 12 with 3

vestal arch
#

just need 2 variables

simple egret
#

Hm yep the curve is out, if the ranges are dynamic

upper pilot
#

So the example above would be: cyclelength = 6f, firstPeak 3f(middle of the cycle?)

simple egret
#

Well you can emulate that in the code, with a class/struct that stores start+end clock times and start+end values

#

And have a list of those

vestal arch
chilly surge
#

You can always just write a bunch of if (time >=0 && time < 12) return ...

upper pilot
untold siren
#

what's the easiest way to do a coroutine where I can interrupt a waitforseconds? would I have to make my own timer with a yield break inside or is there a better method of implementation?

chilly surge
#

Or pattern matching.

vestal arch
#

if the cycle always aligns to midnight then the firstpeak would always be half cyclelength so you wouldn't need a separate input for that

upper pilot
vestal arch
#

if not you'll probably have to make your own CustomYieldInstruction

chilly surge
#

Using actual async/await like with UniTask is also an option, if you are going to work with asynchronous code.

untold siren
#

my idea is
(excuse the rough pseudocode)

IF TIME > 5 seconds AND Condition not met:
  do this function
ELSE OR UNTIL CONDITION MET above
  do another function
rigid island
untold siren
rigid island
#

*reg timer not while loop

untold siren
#

Yeah, had assumed so - I guess the general question was if there was an easier approach when working with coroutines esp since they have yield return new WaitForSeconds()

rigid island
#

what are you trying to do exactly?

simple egret
#

There's this, not sure if that works properly, looks a bit convoluted but hey

float start = Time.time;
yield return WaitUntil(() => Time.time - start > 5 || condition);

if (condition)
    // Condition met
else
    // Timer expired
untold siren
#

sent early mb give me two secs

upper pilot
# vestal arch nah just 1 would be enough
        float cycleLength = 6f;
        float firstPeak = 3f;
        return Mathf.Lerp(0f, 0.3f, 1 - Mathf.Abs(time % cycleLength - firstPeak) / cycleLength);

Am I using it wrong?
At hour 0 it returns 0.15, at hour 3f it returns 0.3f(peak)
Is there a way to tell it which hour I care about? i.e. 2pm to 6pm?(peak being 4pm) -> 14f, 16f(peak), 18f
Right now it seems to just take % of the full day based onn the cycle length, but it doesnt care if its evening, morning etc

untold siren
#
        private IEnumerator PistolRelatedDialogue()
        {
            yield return new WaitForSeconds(1.2f);
            ImageTweening.ChangeTextPromptOnly(ref tutorialTextHint, ref InputPromptTexts, 8);
            yield return new WaitForSeconds(1.8f);
            ImageTweening.ChangeTextPromptOnly(ref tutorialTextHint, ref InputPromptTexts, 9);
        
        }

this is controlling my dialogue in my tutorial once the player collects the pistol - if the player doesn't do what the dialogue is telling them to do so within 10 seconds I want it to change. so was thinking "oh start a timer to determine if the condition has been met yet" - and if the condition isn't met, change the dialogue, if it has been met, then continue

chilly surge
#

With UniTask, it's trivial to express:

await UniTask.WhenAny(
    UniTask.Delay(5000),
    UniTask.WaitUntil(() => condition)
);
untold siren
untold siren
chilly surge
#

That doesn't matter, async/await is just a different way to write coroutines, you can convert between the two.

untold siren
#

oh interesting

#

mad to think I'm finishing uni for games dev in 2 two weeks and have never been tought async / await features in unity ๐Ÿ’€

chilly surge
#

But it depends on how much asynchronous code you are writing, if you deal with a lot of asynchronous stuffs, coroutines is just a caveman version of async/await.

vestal arch
#

yeah i think the last cycleLength needs to be firstPeak

rigid island
chilly surge
#

So are coroutines ๐Ÿ˜„

#

If you have some piece of code that was previously not a coroutine and now you turn it into a coroutine, you have no way but to change the caller to also be a coroutine. That's no less different from async/await.

upper pilot
rigid island
chilly surge
#

But yeah, if you don't write a lot of complex asynchronous logic, coroutines may very well be sufficient even if it's a bit less elegant (eg the question above having you to write out a solution like WaitUntil(() => Time.time - start > 5 || condition) that's difficult to read)
If you deal with lots of asynchronous logic, getting proper async/await makes your life so much easier and code so much more readable.

chilly surge
vestal arch
chilly surge
vestal arch
#

on that note, out of curiousity, what's the equivalent of yield* for c#

chilly surge
#

Nothing about the caller has to change in either coroutine or async/await, if you don't care about the result.

vestal arch
#

yeah, i shouldve inferred that, i just kinda ignored that part of your statement since i didn't want to get into it

rigid island
#

i never said it was trouble

chilly surge
rigid island
#

I said async code in general is

#

cause you have start making almost everything async

chilly surge
rigid island
#

Unity coroutine is easier to deal with than Tasks inside unity specifically

untold siren
vestal arch
#

someone needs to come stand behind me and stop me from doing StopAllCoroutines from inside a coroutine

chilly surge
vestal arch
rigid island
upper pilot
#

i think i wrote it wrong, give me a sec

untold siren
#
        private IEnumerator PistolRelatedDialogue()
        {
            yield return new WaitForSeconds(1.2f);
            ImageTweening.ChangeTextPromptOnly(ref tutorialTextHint, ref InputPromptTexts, 8);
            yield return new WaitForSeconds(1.8f);
            ImageTweening.ChangeTextPromptOnly(ref tutorialTextHint, ref InputPromptTexts, 9);
            var timerStart = Time.time;
            yield return new WaitUntil(() => Time.time - timerStart > 5f || hasFiredPistolYet);
            switch (hasFiredPistolYet)
            {
                case false when !tutorialEnemyDead:
                    ImageTweening.ChangeTextPromptOnly(ref tutorialTextHint, ref InputPromptTexts, 10);
                    break;
                case true when !tutorialEnemyDead:
                    ImageTweening.ChangeTextPromptOnly(ref tutorialTextHint, ref InputPromptTexts, 11);
                    break;
                case true when tutorialEnemyDead:
                    ImageTweening.ChangeTextPromptOnly(ref tutorialTextHint, ref InputPromptTexts, 12);
                    break;
            }

        }

bit messy with the switch statement but it works e_sunglasses

chilly surge
#

Just coroutines not being able to return value alone makes them incredibly annoying to pass results amongst themselves.

rigid island
#

True but hey gotta have trade offs somewhere ig

#

Awaitable class makes things with async more pleasurable in unity

simple egret
# untold siren ```cs private IEnumerator PistolRelatedDialogue() { ...

Heh, something really pretty would be to make ChangeTextPromptOnly return a new WaitForSeconds() that waits for the amount of time needed for the dialogue to appear, so you'd do

yield return ImageTweening.ChangeTextPromptOnly(stuff1);
yield return ImageTweening.ChangeTextPromptOnly(stuff2);

And it waits the perfect amount of time, no more magic numbers

#

But that's for another time. In order: make it work, make it pretty, make it fast

untold siren
simple egret
#

Ahh I see

chilly surge
rigid island
#

well for one Coroutines can work with Timescale but Task.delay for example cannot

simple egret
#

Multiply delay with time scale!

rigid island
#

but again the Awaitable class finally added these to async

#

also things like Fixed time

chilly surge
#

Even in that solution:

float start = Time.time;
yield return WaitUntil(() => Time.time - start > 5 || condition);

If you take a closer look you will see that:

  • You have essentially reinvented WaitForSeconds in the form of keeping a starting time and checking if the time has past.
  • You have essentially reinvented Task.WhenAny in the form of using || to check if either task has completed.
untold siren
#

async propaganda /s

rigid island
latent latch
#

I still dont understand using WaitForSeconds with coroutine over game time

#

frame time for that matter

chilly surge
#

But coroutines have the opposite problem: you have no way to tell it to keep going even if the GO is destroyed.

simple egret
#

Nowadays MonoBehaviour exposes a cancellation token that gets cancelled when the object is destroyed. You do have to check for cancellation yourself though

chilly surge
#

How is that messy?

#

You just pass cancellation token to everything downstream.

untold siren
#

to think a simple question about coroutines would cause a debate between coroutines vs async / await tasks ๐Ÿ’€

latent latch
#

coroutines seem better on manager type systems where the GO isnt destroyed

untold siren
#

tbh

chilly surge
#

You have the choice to ignore cancellation or not ignore it, unlike coroutines where you don't have a choice, it will always cancel when GO is destroyed and you have to work around that.

untold siren
#

I use coroutines because they're easier to understand

rigid island
chilly surge
#

Sure, and that's why I said coroutines are fine for simple stuffs.

swift falcon
#

Hi there, would anyone be able to tell me what the problem is here and how to fix it?

latent latch
#

if I use coroutines it's usually for stuff like menu transitioning, but for like large amounts of them I'm usually just iterating over hashsets or sorted queues and executing logic independently for each

rigid island
#

remove the System using

untold siren