Coder Social home page Coder Social logo

vrchat-community / udonsharp Goto Github PK

View Code? Open in Web Editor NEW

This project forked from merlinvr/udonsharp

467.0 15.0 50.0 13.79 MB

A compiler for compiling C# to Udon assembly

Home Page: https://udonsharp.docs.vrchat.com

License: MIT License

C# 99.13% JavaScript 0.39% CSS 0.09% Batchfile 0.02% PowerShell 0.22% Shell 0.17%

udonsharp's Introduction

UdonSharp

UdonSharp is a compiler that translates C# to Udon assembly, so you can create interactive VRChat worlds by writing C# code.

You can find the full docs at https://udonsharp.docs.vrchat.com.

⚠️ IMPORTANT! ⚠️

The old 0.x version of UdonSharp which used to be delivered as a .unitypackage is deprecated and no longer supported. You can use the Creator Companion to migrate your projects to this new version and keep it updated moving forward.

Requirements

  • Unity 2019.4.31f1
  • VRChat World SDK (can be automatically resolved, see below)

Getting Started

If you're comfortable using GitHub, follow the directions in the UdonSharp Template repo to quickly make your own ready-to-use repository. Otherwise, you can download the VRChat Creator Companion, and then choose Projects > New > UdonSharp to create a new ready-to-use Unity Project.

Use Unity 2019.4.31.f1 to open the project. Press "OK" on the dialog that offers to download the required VRChat packages.

image

Loading the Example World

Find the "VRChat SDK" item in the menu bar at the top of the Unity Editor window, press it to open, then choose "Samples > UdonExampleScene".

samples-udonexample-scene

Once the scene opens, choose "File > Save As..." and give the scene a new name.

Then modify the scene however you'd like - you learn about all the examples in the UdonExampleScene or learn about Getting Started with Udon.

Making your own Scripts

  1. Make a new object in your scene

  2. Add an Udon Behaviour component to your object

  3. Below the "New Program" button click the dropdown and select "Udon C# Program Asset"

  4. Now click the New Program button, this will create a new UdonSharp program asset for you

  5. Click the Create Script button and choose a save destination and name for the script.

  6. This will create a template script that's ready for you to start working on, open the script in your editor of choice and start programming.

    Instead of creating assets from an UdonBehaviour you can also do the following:

  7. Right-click in your project asset explorer

  8. Navigate to Create > U# script

  9. Click U# script, this will open a create file dialog

  10. Choose a name for your script and click Save

  11. This will create a .cs script file and an UdonSharp program asset that's set up for the script in the same directory

Test Your World

When you're ready to try out your World, find and choose the menu item "VRChat SDK > Show Control Panel".

  • Sign into your VRChat Account in the "Authentication" tab.
  • Switch to the "Builder" tab and choose "Build & Test".
  • After a quick build process, VRChat should open up in your test world!
  • If you have any issues making a test world, check out our docs on Using Build & Test.

Publish Your World

When you're ready to publish your World so you can use it regularly:

  • Return to the VRChat SDK Control Panel in your Unity Project
  • Switch to the "Builder" tab and press "Build and Publish for Windows".
  • This will build your World and add some publishing options to your Game window.
  • Fill out the fields "World Name", "Description" and "Sharing", and check the terms box "the above information is accurate...".
  • Press "Upload".

Return to VRChat - open the "Worlds" menu, then scroll down to the section named "Mine". Choose your world from the list and press "Go" to check it out!

Visual Studio Code Integration

You can follow this video guide to get Intellisense for C# within your Unity project in Visual Stido Code (VS Code), inlcuding libraries such as UdonSharp.

Credits

  • See CONTRIBUTORS.md for people who have helped provide improvments to UdonSharp
  • The open source project Harmony helps Udonsharp provide a better editor experience

Discord

udonsharp's People

Contributors

abbodarr avatar anatawa12 avatar arne-van-der-lei avatar bdunderscore avatar chanyavrc avatar cnlohr avatar fairlysadpanda avatar faxmashine avatar float3 avatar forwrya avatar greedboy-55 avatar happyrobot33 avatar hogashi avatar hyblocker avatar merlinvr avatar mika-f avatar momo-the-monster avatar nathanc avatar nestorboy avatar norkel avatar norkel-vrc avatar orels1 avatar pema99 avatar phaxenor avatar reimajo avatar shaundreclin avatar simonknittel avatar toocanzs avatar unihedro avatar ureishi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

udonsharp's Issues

If an UdonSharp script is placed in a Plugins folder, it causes the 'Does Not Belong to a U# Assembly' error.

Describe the bug in detail:
If when trying to organise a project, you place an UdonSharp code file within a Unity folder path of 'Assets\Plugins', this causes the file to be unable to compile with the 'Does Not Belong to a U# Assembly' error.
This is due to Unity's magic behaviour of script files within the Plugins folder being compiled by the Assembly-CSharp-firstpass.dll instead of the normal Assembly-CSharp.dll.
If someone is unaware of this magic (as I was for several hours!) and attempt to use a folder named Plugins to tidy up say, external U# libraries or packages they've installed in their project, this will cause a significant headache.

Provide steps/code to reproduce the bug:

  1. Create a folder in the root of a World project named 'Plugins'.
  2. Use the right-click menu in the Project window menu or the 'New U# Script' option on a blank Udon component to create a script with any name in the folder.
  3. Navigate to the script's matching Assembly file and click the 'Compile all UdonSharp programs' button.

Expected behavior:
If the compiler can't find the Udon Assembly file, it performs a sanity check on the path of the script file and if its within Plugins, a warning or similar message to the console or in a popup box, informing the developer they can't place U# scripts within 'Assets\Plugins' and that they'll need to move it somewhere else.

How to get/set `UdonBehaviour.InteractionText` on `this`?

InteractionText does not appear to be available on UdonSharpBehaviour. You can, however, get/set it on an UdonBehaviour instance and it compiles and works as expected (as in reading the right value and displaing the given value).

I'd have expected InteractionText to be on UdonSharpBehaviour, however I would not be surprised if you had to get the UdonBehaviour of this to get access to it, but if that's the case, well, I don't know how to get said UdonBehaviour outside of using GetComponent which is not only cumbersome and has the issue with multiple UdonBehaviours on one GameObject (well, maybe. Not sure how InteractionText is implemented in this regard but it's besides the point). Plus it would be weird if that was the intentional way to get/set InteractionText on this.

Ultimately I'm asking if I'm missing something or if InteractionText was simply missed and should be added to UdonSharpBehaviour.

Enum types do not have bitwise operators defined

Describe the bug in detail:
Can not use bitwise and (&) or bitwise or (|) with enums.

Provide steps/code to reproduce the bug:
Define an enum and somewhere in a udon behavior use the bitwise operators.

Expected behavior:
Should behave like ints and combine the two values rather than compiler errors

Additional Information:
image

Udon ignore compile constant

Compile time constant (ex UDON_COMPILE) that is false only when udon compiles the script/ignores everything inside the #if compile check.

I'm trying to make use of some MyBox attributes to make sorting things in the inspector easier and being able to use them while Udon doesn't throw a fit would be nice.

Inline Code isn't working anymore

I just noticed the Inline Code option in udonsharp isn't doing anything anymore. Not sure if this is important feature or not. Just reporting here.

[1.1.5] UdonSharp spams log with unserialized data errors at runtime when you have unserializable data

Describe the bug in detail:
When using helper data structures in UdonSharp which aren't used at runtime, UdonSharp still complains every frame about not being able to serialize the data in that member. This is very spammy, and a singular error at the top of the log would be fine.

Provide steps/code to reproduce the bug:
Define some sort of serializable struct:

[Serializable]
public struct MyStruct {
    public string myString;
    public int myInt;
}

Use it in your UdonBehaviour:

public class MyUdonSharpClass : UdonSharpBehaviour {
    public MyStruct myStructMember;
    public int myIntMember;
    // Other variables and methods
}

Expected behavior:
UdonSharp complains only once about not being able to serialize MyStruct

Additional Information:
I use structs in some of my UdonSharp behaviours to assist editor scripts, particularly nested arrays using reorderable lists. In earlier versions of U# I'd get one error about not being able to serialize the data, and I was relying on U# to just exclude that data from the UdonBehaviour and not being too fussy about it, since I replicate it over to Udon Compatible arrays in editor. Unfortunately these Udon compatible arrays are not reorderable list friendly and I require the nested structs arrays.

VPM .unitypackage fails to build

Describe the bug in detail:
We get this error when trying to make a .unitypackage for an UdonSharp release.

file:///home/runner/work/_actions/pCYSl5EDgo/create-unitypackage/cfcd3cf0391a5ef1306342794866a9897c32af0b/node_modules/js-yaml/dist/js-yaml.mjs:1273
  return new exception(message, mark);
         ^
YAMLException: incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line (15:7)

 12 |   validateReferences: 1
 13 |   platformData:
 14 |   - first:
 15 |       : Any
------------^
 16 |     second:
 17 |       enabled: 0

Error in UdonSharpPrefabDAG constructor breaks prefabs

Describe the bug in detail:
Error in UdonSharpPrefabDAG constructor breaks prefabs

Provide steps/code to reproduce the bug:
import U# 0.x version (1.3.4) of https://booth.pm/ja/items/2683599 (see also #104)

Expected behavior:
I think U# should not migrate prefabs in such a case and show dialog to tell users instead.

Additional Information:
Provide any additional information here.

Some errors like this screenshot will be displayed because of U# migration. (This is error dialog on macOS but this error will also be happened on windows.)

image

Change/Remove `serializedUdonProgramAsset`'s guid to be source control friendly

First of all a disclaimer, I'm still using v0.20.3 because that's the latest release on github and to my knowledge the latest one that isn't using the VRChat Creator Companion. However I don't believe this has changed in later versions, but if it has let me know.

Feature Description:
When one has an UdonSharp script with an asset file along side it and said files have just been copied into the project through some method, the file reference guid in serializedUdonProgramAsset should remain unchanged, which means the guid in the meta file for a file in SerializedUdonPrograms should be set to the same guid as storedd in serializedUdonProgramAsset instead of making a new one.
I don't know if this is possible with unity, it's outside of my editor scripting knowledge, so if it isn't possible then the other option I can think of is removing serializedUdonProgramAsset from the asset file for UdonSharp entirely. I believe this would then require some other editor script which when initialized figures out the references from UdonSharp asset files to files in SerializedUdonPrograms, which would require those references to either be stored in SerializedUdonPrograms or another file that just stores references maybe in the Library folder. Once again, I don't know enough to say which works or is better or worse.

Additional context:
However to help you better asses the issue, here's why - in my opinion - this is a serious issue:

serializedUdonProgramAsset changes between projects for the same scripts (copies) because the files in SerializedUdonPrograms aren't copied over. This is a big problem when trying to use UdonSharp in a project with version control, because every time you check out the changes someone else made all of your guids get changed, but they then change again once you go back to unity since those guids weren't your guids. In version control systems with file locking this means that basically every asset file needs to be locked whenever you're working on something potentially preventing any other person working on the same project as you are at the same time (if my understanding of those systems is correct) and the files will always appear as changed even though nothing really changed, just the guid. In version control systems without file locking all asset files also constantly change, but there's a very good chance of merge conficts for every asset file once multiple people start working at the same time or on different branches which at some point get merged.
Including SerializedUdonPrograms in version control is first of all simply wrong because those files are 100% generated and secondly not even an option if you aren't version controlling the root of the project. For example if you have Assets/MyScripts as the root of the repository, SerializedUdonPrograms is entirely outside of the repo.

I've thought about workarounds, specifically when using git and gitlfs, and I won't explain all of the thoughts I had on it already but even just a workaround requires dozends of hours of work and still has preformance concerns.

If there's any other solution to this problem that doesn't involve changing how serializedUdonProgramAsset works I'd also be happy to know.

2D arrays are no longer displayed in inspector.

Describe the bug in detail:
Previously, 2D arrays with public or [SerializeField] attributes were displayed in inspector in UdonSharp, but they are no longer displayed in UdonSharp now.

Image 1:Code
スクリーンショット (370)

Image 2:inspector of v0.20.3
スクリーンショット (371)

Image 3: inspector of v1.0.0b9
スクリーンショット (372)

Provide steps/code to reproduce the bug:

  1. Descrive 2D arrays with public or [SerializeField] attributes and attache to UdonBehaviour
  2. See Inspector(always occuer)

Expected behavior:
2D arrays should be display in inspector.
The Udon gimmick that allows users to set parameters in a 2D array is no longer available, and should be fixed.

Additional Information:
I wrote same issue in VRChat canny.
https://feedback.vrchat.com/vrchat-udon-closed-alpha-bugs/p/2d-arrays-are-no-longer-displayed-in-inspector

Implement IUdonEventReceiver interface on UdonSharpBehaviour

Feature Description:
This one's pretty simple, I want UdonSharpBehaviour to implement the interface IUdonEventReceiver to make it work with the new image downloader class.

Additional context:
When trying to pass this into VRCImageDownloader.DownloadImage() I get a compile error. I tried adding IUdonEventReceiver to the list of interfaces to the UdonSharpBehaviour class myself and it required a bunch of internal vrchat jargon we didn't need, but was necessary for the interface to work. As it stands right now, unless using hacky methods, we cannot pass the current behaviour into the DownloadImage() method. As such this may be an upstream problem I'm willing to file a canny for. Either that or I'm just doing it wrong.

UnityEditor Crash by UdonSharp compile

Describe the bug in detail:
2022-06-12 231519

I'm not sure why .
I guess compiling string + property has some bug.
but when i use string.format to replace that code ,it will fix the problem.

Migration of prefab with UdonSharp 0.20.3 project to 1.x is broken

Describe the bug in detail:

Migrating prefab made with UdonSharp 0.20.3 to 1.x is broken in some case.
In similar case, prefab with UdonGraph will not be broken so I think this is bug of UdonSharp.

Provide steps/code to reproduce the bug:

  1. create/open project with UdonSharp 1.x.
  2. import UdonSharpTest.unitypackage in UdonSharpTest.unitypackage.zip

Expected behavior:

In 1.OuterObject/2.InnerObject of UdonSharpTest/1.OuterObject.prefab, the value of Test Color is black (as if we imported to project with old SDK).

Actual behavior:

In 1.OuterObject/2.InnerObject of UdonSharpTest/1.OuterObject.prefab, the value of Test Color is white, the color specified in 2.InnerObject.prefab.

Additional Information:

In 3.InnerObject.prefab, Test Color is black, as we imported to old SDK.

[1.0.0 | 1.0.1] OnPlayerTriggerEnter does not work

Describe the bug in detail:
OnPlayerTriggerEnter Exit etc do not work. They don't trigger anything. OnTriggerEnter triggers fine.

Provide steps/code to reproduce the bug:

  • Create new project using U# 1.0.1 or 1.0.0
  • Create basic scene to walk around in and add
    • a gameobject with a box collider set to trigger
    • a rigidbody set to kinematic
    • a new U# script
  • In the U# script, override OnPlayerTriggerEnter and add a debug.log (or activate/deactivate a gameobject for build testing)
  • Play or build and walk into the trigger
  • No Debug log is sent to console / trigger isn't triggered

Expected behavior:
OnPlayerTriggerEnter should trigger when players enter a collider set to trigger on the same or child objects

Additional Information:
I can provide a repro project if needed, but it's not a complex setup.

Enum types use enum value rather than enum name when converted to string

Describe the bug in detail:
In C#, when you use ToString() on an enum type, it will return the name of the enum value, while in U# it returns the integer converted to a string. This is undesirable behavior most of the time, and unaligned with C#'s behavior.

Provide steps/code to reproduce the bug:
Let's take this enum for instance:

public enum MyEnum {
    MyFirstValue,
    MySecondValue
}

If we print it out like this, we should see the problem:

MyEnum myEnumInstance = MyEnum.MyFirstValue;
Debug.Log(myEnumInstance.ToString());

Expected behavior:
Log should read "MyFirstValue"

Observed behavior:
Log actually reads "0"

[1.1.5] Extended methods with variadic arguments eat the first element

Describe the bug in detail:

When calling an extended method that has variadic arguments, the first element of the variadic argument disappears.

Provide steps/code to reproduce the bug:

public static void Dump(this string value, params string[] args)
{
    Debug.Log($"Dump: {value}, {string.Join(", ", args)}");
}
"a".Dump("b", "c", "d");

Expected behavior:

Expected:

Dump: a, b, c, d

Actual:

Dump: a, c, d

Additional Information:

If I pass no arguments to the above function, it should generally receive an empty array as a variadic argument, but a compile error occurs.

[UdonSharp] Assets/Scripts/Resources/ResultPreviewer.cs(50,9): System.OverflowException
  at (wrapper managed-to-native) System.Object.__icall_wrapper_ves_icall_array_new_specific(intptr,int)
  at UdonSharp.Compiler.Binder.BinderSyntaxVisitor.VisitInvocationExpression (Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax node) [0x0037c] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\BinderSyntaxVisitor.cs:471 
  at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult] (Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1[TResult] visitor) [0x00000] in <9c2eb1fd370b4c31a981729c5e257f1b>:0 
  at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1[TResult].Visit (Microsoft.CodeAnalysis.SyntaxNode node) [0x00003] in <9c2eb1fd370b4c31a981729c5e257f1b>:0 
  at UdonSharp.Compiler.Binder.BinderSyntaxVisitor.Visit (Microsoft.CodeAnalysis.SyntaxNode node) [0x00065] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\BinderSyntaxVisitor.cs:51 
  at UdonSharp.Compiler.Binder.BinderSyntaxVisitor.VisitExpressionStatement (Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax node) [0x00001] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\BinderSyntaxVisitor.cs:270 
  at Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax.Accept[TResult] (Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1[TResult] visitor) [0x00000] in <9c2eb1fd370b4c31a981729c5e257f1b>:0 
  at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1[TResult].Visit (Microsoft.CodeAnalysis.SyntaxNode node) [0x00003] in <9c2eb1fd370b4c31a981729c5e257f1b>:0 
  at UdonSharp.Compiler.Binder.BinderSyntaxVisitor.Visit (Microsoft.CodeAnalysis.SyntaxNode node) [0x00065] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\BinderSyntaxVisitor.cs:51 
  at UdonSharp.Compiler.Binder.BinderSyntaxVisitor.VisitBlock (Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax node) [0x00049] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\BinderSyntaxVisitor.cs:261 
  at Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.Accept[TResult] (Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1[TResult] visitor) [0x00000] in <9c2eb1fd370b4c31a981729c5e257f1b>:0 
  at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1[TResult].Visit (Microsoft.CodeAnalysis.SyntaxNode node) [0x00003] in <9c2eb1fd370b4c31a981729c5e257f1b>:0 
  at UdonSharp.Compiler.Binder.BinderSyntaxVisitor.Visit (Microsoft.CodeAnalysis.SyntaxNode node) [0x00065] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\BinderSyntaxVisitor.cs:51 
  at UdonSharp.Compiler.Symbols.MethodSymbol.Bind (UdonSharp.Compiler.Binder.BindContext context) [0x00170] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\Symbols\MethodSymbol.cs:162 
  at UdonSharp.Compiler.Symbols.UdonSharpBehaviourMethodSymbol.Bind (UdonSharp.Compiler.Binder.BindContext context) [0x000b5] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\Symbols\UdonSharpBehaviourMethodSymbol.cs:55 
  at UdonSharp.Compiler.Symbols.TypeSymbol.Bind (UdonSharp.Compiler.Binder.BindContext context) [0x00193] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\Symbols\TypeSymbol.cs:137 
  at UdonSharp.Compiler.Binder.BindContext.Bind () [0x0001b] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\Binder\BindContext.cs:35 
  at UdonSharp.Compiler.UdonSharpCompilerV1+<>c__DisplayClass22_0.<BindAllPrograms>b__0 (System.ValueTuple`2[T1,T2] rootTypeSymbol) [0x00030] in C:\Users\kurone-kito\src\my\the-mind-mirror\Packages\com.vrchat.udonsharp\Editor\Compiler\UdonSharpCompilerV1.cs:618 

the value of VRCPlayerApi type become null after substitution on OnOwnershipTransferred

Describe the bug in detail:
When OnOwnershipTransferred(VRCPlayerAPi owner_player) is called,"owner_player" is inputed to "player" variable.
then, "onwer_player.playerId" is inputed to "player_id" variable.
(player & player_id variable is member variable of the class that call the OnOwnershipTransferred(). )
But, In LateUpdate() , "player" variable show null. player_id is not null.

May be my code is wrong simply.

Provide steps/code to reproduce the bug:

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class JoinToGame : UdonSharpBehaviour
{
[SerializeField] PlayerStatusCollision psc;
[SerializeField] TextMeshProUGUI dtext;

public override void Interact(){
    dtext.text = "OnInteract()" + "\n" + dtext.text;
    if(!psc.PlayerIsLocalPlayer()) psc.SetOwnerWithInteract();        
}

}

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class PlayerStatusCollision : UdonSharpBehaviour
{
public int player_id;
public VRCPlayerApi player;
[SerializeField] TextMeshProUGUI dtext;

public bool PlayerIsLocalPlayer(){
    if(player == null) return false;
    if(player.playerId == Networking.LocalPlayer.playerId) return true;
    return false;
}

public void SetOwnerWithInteract(){      
    if(Networking.IsOwner(Networking.LocalPlayer,gameObject)){            
        dtext.text = "SetOwnerWithInteract-owner is local player" + "\n" + dtext.text;
        SendCustomNetworkEvent(NetworkEventTarget.All,nameof(SetPlayerWithOwner));
    }else{
        dtext.text = "SetOwnerWithInteract-owner is not local player" + "\n" + dtext.text;
        Networking.SetOwner(Networking.LocalPlayer,gameObject);            
    }
}

public void SetPlayerWithOwner(){
    dtext.text = "SetOwnerWithMaster" +"\n" + dtext.text;
    player = Networking.GetOwner(gameObject);     
    player_id = player.playerId;                                                                          
}

public override void OnOwnershipTransferred(VRCPlayerApi owner_player){
    dtext.text = "OnOwnershipTransferred-owner_player.playerId" + owner_player.playerId.ToString() + "\n" + dtext.text;
    player = owner_player;        
    player_id = owner_player.playerId;
    dtext.text = "OnOwnershipTransferred-player.playerId-" + player.playerId.ToString() + "\n" + dtext.text;
}           

float dtime = 0;
void LateUpdate()    
{                
    dtime += Time.deltaTime;
    if(dtime > 5 && player == null)
    {
        dtext.text = "LateUpdate()-player is null" + "\n" + dtext.text;
        if(player_id != null){
            dtext.text = "LateUpdate()-player_id is not null" + "\n" + dtext.text;
            player = VRCPlayerApi.GetPlayerById(player_id);
        }else{
            dtext.text = "LateUpdate()-player_id is null" + "\n" + dtext.text;
        }
    }
    if(Utilities.IsValid(player)){        
        if(dtime > 5) dtext.text = "LateUpdate()-IF-"+ player.playerId.ToString() + "\n" + dtext.text;
        Vector3 pos = player.GetBonePosition(HumanBodyBones.Spine);             
        gameObject.transform.position = pos;
        gameObject.transform.rotation = player.GetBoneRotation(HumanBodyBones.Hips);
    }else{
        if(dtime > 5) dtext.text = "LateUpdate()-else-"+ "\n" + dtext.text;
    }

    if(dtime > 5) dtime = 0;

}

}

Expected behavior:
What was the excepted result?

Additional Information:
Provide any additional information here.

Using Namespaces outputs an Error when .cs is saved from JetBrains Rider before attempting a recompile.

Describe the Bug in Detail:
Using an UdonSharpBehaviour Class inside a namespace {} will cause the compiler to error on it. On rare occasions, it may break. Although it will successfully recompile, I do not like seeing that Error show after saving the .cs from an external editor.

I do not want an Error to appear when all UdonSharp Code is built inside a namespace {} and is saved from an External Editor, since all functions must be written inside a namespaces when it is used. Because of this Error, I have to double-check with a manual UdonSharp Recompile so that there is no error whatsoever (which is the case).

Steps to Reproduce:
Simply create a new U# Script as usual, edit in JetBrains Rider (which is what I'm using) using a namespace {}. Save your Code and the Unity Project will refresh. You'll see the compile progress bar disappear midway and output an Error, followed by (hopefully) a clean Asset refresh with successful compile.

Expected Behavior:
UdonSharp compiles the code as per usual without Errors upon refresh.

Additional Information:
Using UdonSharp v1.1.6
The Editor I'm using is JetBrains Rider, which is what I prefer for editing C#. I am unsure if this bug affects Visual Studio or if it's just because I'm using JetBrains Rider.

Add where to find UdonSharp

Feature Description:
Add to the readme that the newest version of U# can only be found in the VCC.

Additional context:
I have been looking around for another way to install the newest version of U# (1.0+), and it seems that the only way to do so right now is through the VCC. I am not sure if this is because it's in beta or if this is just the way this will stay in the future, but since right now I had to find this out by searching in the discord, this might be a good thing to put in the readme.

[1.1.1] Using range comparison on enum compiles into wrong extern

Describe the bug in detail:
Doing a range comparison (such as less-than-or-equal) for an enum value without explicit int casting incorrectly compiles to the SystemInt32.__op_Inequality__SystemInt32_SystemInt32__SystemBoolean extern.

Provide steps/code to reproduce the bug:
Create a C# script with the following code and the examine the compiled UASM:

namespace BugTesting
{
    public enum TestLevel { ZERO, ONE, TWO}
    public class EnumComparators : UdonSharp.UdonSharpBehaviour
    {
        public TestLevel level;

        private void Start()
        {
            bool _ = TestLevel.ONE <= level;
            _ = (int)TestLevel.ONE <= (int)level;
        }
    }
}

Outputs:

.data_start
    .export level
    __refl_typeid: %SystemInt64, null
    __refl_typename: %SystemString, null
    __intnl_returnJump_SystemUInt32_0: %SystemUInt32, null
    level: %SystemInt32, null
    __const_SystemUInt32_0: %SystemUInt32, null
    __const_SystemInt32_0: %SystemInt32, null
    __lcl___SystemBoolean_0: %SystemBoolean, null
.data_end
.code_start
    .export _start
    _start:
        PUSH, __const_SystemUInt32_0
# 
# BugTesting.EnumComparators.Start()
# 
        PUSH, __const_SystemInt32_0
        PUSH, level
        PUSH, __lcl___SystemBoolean_0
        EXTERN, "SystemInt32.__op_Inequality__SystemInt32_SystemInt32__SystemBoolean"
        PUSH, __const_SystemInt32_0
        PUSH, level
        PUSH, __lcl___SystemBoolean_0
        EXTERN, "SystemInt32.__op_LessThanOrEqual__SystemInt32_SystemInt32__SystemBoolean"
        PUSH, __intnl_returnJump_SystemUInt32_0
        COPY
        JUMP_INDIRECT, __intnl_returnJump_SystemUInt32_0
.code_end

Expected behavior:
Enums are always treated as ints within udon, so the comparison should match the respective comparison extern, such as SystemInt32.__op_LessThanOrEqual__SystemInt32_SystemInt32__SystemBoolean

Add cahcing list feature on Class Exposure Tree

Feature Description:
I want to keep Class Exposure Tree window opened. that I can serach reference any time.
But everytime I've edited c# code. the Class Exposure Tree will call reload. It takes a quite long time. wich is very annoying .
Although I'm editing my code , that won't change any engine source nor udon sdk source .
So use caching list rather than reload every time, additinally add a manually refresh button.

Re add “compile all scripts” option

Re add option to not compile all scripts every time one script changes.

Also, whenever changing a script that isn’t related to udonsharp, it compiles all udon sharp behaviours anyways. I have a slow laptop and a lot of udon in my project and it takes a long time. Could you add an option that can stop udonsharp from compiling when a non udon script is changed?

the docs also still show the setting I mentioned
298AD172-696D-4A5A-8346-C80C46B76322

Add Release Notes to Docs

Feature Description:
It would be great to include release notes for each version in the generated docs like ClientSim and VCC have.

Additional context:
I'll do it!

Help users resolve 'Udon C# Program Asset is null' error

Feature Description:
Users often create empty Udon C# Program Assets. This prevents UdonSharp from compiling.
Users often do not understand the error. Possible reasons:

  • They're inexperienced with UdonSharp
  • They received their UdonSharp assets from someone else
  • They created the Asset on accident and forgot about it
  • Double-clicking the error does not highlight the asset (Unconfirmed)

Regardless, we should help users identify the issue, and suggest a solution.

For example:

  • The error should indicate that the file should either be deleted, or a source C# script should be added
  • The error could be downgraded to a warning, as was the case before U# 1.0

"!>" (not greater than) generates exception not caught by UdonSharp

This line of code: if (otherNeso.isPanicing && Vector3.Distance(transform.position, otherNeso.transform.position) < 0.4 && interactionType != 3 && interactionStep !> 0)

THe last comparison in this if statement generates an exception: Apparently !> is not a symbol recognized by UdonSharp. This generates an unhelpfull error: Error: Could not load signature of VRC.SDK3.Components.MultipleDisplayUtilities:GetRelativeMousePositionForDrag due to: Could not load file or assembly 'UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type: member:(null) signature:

It seems that this symbol is not a standard operator, but the errors generated by its use are very unhelpful. It could be good to insert at least some sort of error message...I spent a few days trying to figure out what the heck was going on >_<

Add support for custom ASMDEF defines in UdonSharpBehaviours

Feature Description:
Currently U# does not support compile flags defined within ASMDEF files for VPM packages within UdonSharpBehaviours. This method of handling define flags will be used more in the future and being able to integrate these flags into UdonSharpBehaviours would be very useful.

Additional context:
And example of utilizing custom ASMDEF define in an UdonSharpBehaviour:
https://gitlab.com/techanon/protv/-/blob/9afd72f3e7f745ff9049ffb22a311dfd58af8dd6/Runtime/AudioLinkAdapter/AudioLinkAdapter.cs

Proxy function to handle prefab modifications

Feature Description:
This would be a function on the base UdonSharpBehaviour class that checks if the gameobject the target behaviour is on is part of any prefab, and if yes, records prefab instance modifications for the behaviour. It could speed up adding proper prefab support to custom inspectors and editor scripts.

Additional context:
For example something like this:

public void HandlePrefabModifications()
{
    if (PrefabUtility.IsPartOfAnyPrefab(gameObject))
    {
        EditorUtility.SetDirty(this);
        PrefabUtility.RecordPrefabInstancePropertyModifications(this);
    }
}

In the custom inspector, you could then simply do

EditorGUI.BeginChangeCheck();
someBehaviour.someStringProperty = EditorGUILayout.TextField("String property: ", someBehaviour.stringProperty);
if (EditorGUI.EndChangeCheck())
{
    someBehaviour.HandlePrefabModifications();
}

Allow UdonSharp to be downloaded via unitypackage

Feature Description:
Allow UdonSharp to be downloaded via unitypackage

Additional context:
Many users still have not downloaded the VCC. There is still the ability for people to create projects through the template repos on github. However, there doesn't seem to be a way to install the latest version of UdonSharp, which a lot of projects rely on.

Expose exported Method and Parameter names in UdonSharpProgramAsset

Feature Description:
Please expose the public methods with variable names for the parameters and return value as well as property names so that editor scripts can access this information. Field Definitions are already exposed in UdonSharpProgramAsset and a similar dictionary for methods and properties would be sufficient solution.

For context on why I would like this feature, my goal is to build support into CyanTrigger to easily work with U# programs.

When using SetOwner from not owner player, strange problem happen

I will write the code and the result of it.

U# version : 1.1

pattern1
this is correct pattern.

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class GameMastar : UdonSharpBehaviour{

    [SerializeField] GameReady game_ready;
    [SerializeField] EachLocalDataForSyncList eld_list;

    [SerializeField] FootSoundList foot_sound_list;

    public void Phase1Ready(){
        
        GeneralMethods.OutLog("Phase1Ready");
        if(!Networking.IsMaster) {
            GeneralMethods.OutLog("Not Master");
            return;        
        }
        VRCPlayerApi[] players = GeneralMethods.GetPlayers();
        game_ready.SetFootSound(players); 
        game_ready.SetEachLocalDataForSync(players);
        WaitReadyEachLocalDataForSync();
    }

    public void WaitReadyEachLocalDataForSync(){
        GeneralMethods.OutLog(nameof(WaitReadyEachLocalDataForSync));
        if(game_ready.ConfirmEachLocalDataFoySyncOwner()){
            Phase2Ready();
        }else{
            SendCustomEventDelayedSeconds(nameof(WaitReadyEachLocalDataForSync),2.0f, EventTiming.Update);
        }

    }

    public void Phase2Ready(){
        GeneralMethods.OutLog("Phase2Ready");
        FootSound[] kk =  (FootSound[])foot_sound_list.GetList();
        GeneralMethods.OutLog("FootSound player_id :" + kk[0].GetTargetPlayerId().ToString());
        GeneralMethods.OutLog("FootSound player_id :" + kk[1].GetTargetPlayerId().ToString());
    }

//ユーザーごとのローカルデータ共有用のクラス

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class EachLocalDataForSync : BaseUserData
{
    [UdonSynced,HideInInspector] public int[] auto_skill_id = {-1,-1,-1};
    [UdonSynced,HideInInspector] public int manual_skill_id = -1;

    protected override void WhenTargetPlayerIdSeted(){
        base.WhenTargetPlayerIdSeted();
        if(Networking.IsOwner(Networking.LocalPlayer,gameObject)){
            ChangeOwnerToTargetPlayer();
        }

    }
}

result:
R0

pattern2

//same as pattern1
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class GameMastar : UdonSharpBehaviour{

    [SerializeField] GameReady game_ready;
    [SerializeField] EachLocalDataForSyncList eld_list;

    [SerializeField] FootSoundList foot_sound_list;

    public void Phase1Ready(){
        
        GeneralMethods.OutLog("Phase1Ready");
        if(!Networking.IsMaster) {
            GeneralMethods.OutLog("Not Master");
            return;        
        }
        VRCPlayerApi[] players = GeneralMethods.GetPlayers();
        game_ready.SetFootSound(players); 
        game_ready.SetEachLocalDataForSync(players);
        WaitReadyEachLocalDataForSync();
    }

    public void WaitReadyEachLocalDataForSync(){
        GeneralMethods.OutLog(nameof(WaitReadyEachLocalDataForSync));
        if(game_ready.ConfirmEachLocalDataFoySyncOwner()){
            Phase2Ready();
        }else{
            SendCustomEventDelayedSeconds(nameof(WaitReadyEachLocalDataForSync),2.0f, EventTiming.Update);
        }

    }

    public void Phase2Ready(){
        GeneralMethods.OutLog("Phase2Ready");
        FootSound[] kk =  (FootSound[])foot_sound_list.GetList();
        GeneralMethods.OutLog("FootSound player_id :" + kk[0].GetTargetPlayerId().ToString());
        GeneralMethods.OutLog("FootSound player_id :" + kk[1].GetTargetPlayerId().ToString());
    }
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class EachLocalDataForSync : BaseUserData
{
    [UdonSynced,HideInInspector] public int[] auto_skill_id = {-1,-1,-1};
    [UdonSynced,HideInInspector] public int manual_skill_id = -1;

    protected override void WhenTargetPlayerIdSeted(){
        base.WhenTargetPlayerIdSeted();  
        if(Networking.LocalPlayer.playerId == target_player_id){
            ChangeOwnerToTargetPlayer();
        }

    }
}

result :
R1

FootSound player_id Should not have 0, should have 2.

pattern3


[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class GameMastar : UdonSharpBehaviour{

    [SerializeField] GameReady game_ready;
    [SerializeField] EachLocalDataForSyncList eld_list;

    [SerializeField] FootSoundList foot_sound_list;

    public void Phase1Ready(){
        
        GeneralMethods.OutLog("Phase1Ready");
        if(!Networking.IsMaster) {
            GeneralMethods.OutLog("Not Master");
            return;        
        }
        VRCPlayerApi[] players = GeneralMethods.GetPlayers();
        game_ready.SetFootSound(players);        
        game_ready.SetEachLocalDataForSync(players);
        WaitReadyEachLocalDataForSync();
    }

    public void WaitReadyEachLocalDataForSync(){
        GeneralMethods.OutLog(nameof(WaitReadyEachLocalDataForSync));
        FootSound[] kk =  (FootSound[])foot_sound_list.GetList();
        GeneralMethods.OutLog("FootSound player_id :" + kk[0].GetTargetPlayerId().ToString());
        GeneralMethods.OutLog("FootSound player_id :" + kk[1].GetTargetPlayerId().ToString());
        if(game_ready.ConfirmEachLocalDataFoySyncOwner()){
            Phase2Ready();
        }else{
            SendCustomEventDelayedSeconds(nameof(WaitReadyEachLocalDataForSync),2.0f, EventTiming.Update);
        }

    }

    public void Phase2Ready(){
        GeneralMethods.OutLog("Phase2Ready");
        FootSound[] kk =  (FootSound[])foot_sound_list.GetList();
        GeneralMethods.OutLog("FootSound player_id :" + kk[0].GetTargetPlayerId().ToString());
        GeneralMethods.OutLog("FootSound player_id :" + kk[1].GetTargetPlayerId().ToString());
    }

same as pattern2

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class EachLocalDataForSync : BaseUserData
{
    [UdonSynced,HideInInspector] public int[] auto_skill_id = {-1,-1,-1};
    [UdonSynced,HideInInspector] public int manual_skill_id = -1;

    protected override void WhenTargetPlayerIdSeted(){
        base.WhenTargetPlayerIdSeted();  
        if(Networking.LocalPlayer.playerId == target_player_id){
            ChangeOwnerToTargetPlayer();
        }

    }
}

result :
R2

If access to player_id value before Phase2Ready, player_id become correct value.

++++OtherCode

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using VRC.Udon.Common.Interfaces;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class BaseUserData : UdonSharpBehaviour
{
    [UdonSynced,FieldChangeCallback(nameof(SyncedTargetPlayerId))] protected int target_player_id = -1;        
    protected VRCPlayerApi target_player = null;

    public bool IsUsed(){
        if(target_player_id != -1 && Utilities.IsValid(target_player)) return true;
        return false;
    }

    public bool IsTargetPlayerBeOwner(){
        if(target_player == null) return true;
        if(Networking.IsOwner(target_player,gameObject)) return true;
        return false;
    }

    public int GetTargetPlayerId(){
        return target_player_id;
    }
    int SyncedTargetPlayerId{
        get => target_player_id;
        set { 
            target_player_id = value;
            if(target_player_id != -1){
                WhenTargetPlayerIdSeted();
            }
        }
    }

    protected virtual void WhenTargetPlayerIdSeted(){
        target_player = VRCPlayerApi.GetPlayerById(target_player_id);
    }

    public void ChangeOwnerToTargetPlayer(){
        if(target_player == null) return;
        Networking.SetOwner(target_player,gameObject);
    }

    public void SetPlayer(int player_id){
        if(!Networking.IsOwner(Networking.LocalPlayer,gameObject)){
            GeneralMethods.OutLog("BaseUserData.SetPlayer : not owner");
            return;
        }
        SetProgramVariable("target_player_id",player_id);
        RequestSerialization();
    }

    public void SyncReset(){      
        if(!IsUsed()) return;
        SendCustomNetworkEvent(NetworkEventTarget.All,nameof(Reset));
        Networking.SetOwner(GeneralMethods.GetMaster(),gameObject);
    }

    public virtual void Reset(){
        target_player_id = -1;
        target_player = null;
    }               

    public override void OnPlayerLeft(VRCPlayerApi player){
        if(Networking.IsOwner(Networking.LocalPlayer,gameObject)){
            if(player.playerId == target_player_id){
                SyncReset();
            }
        }
    }

    public override void OnPlayerJoined(VRCPlayerApi player){
        if(Networking.IsOwner(Networking.LocalPlayer,gameObject)){
            RequestSerialization();
        }        
    }

}
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using VRC.Udon.Common.Interfaces;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class FootSound : BaseUserData
{
    [SerializeField] AudioSource run_sound;
    [SerializeField] AudioSource walk_sound;
    private bool is_walk_sound_playing = false;
    private bool is_run_sound_playing = false;    
    void LateUpdate(){
        if(Utilities.IsValid(target_player)){
            transform.position = target_player.GetPosition();            
            float spd = target_player.GetVelocity().magnitude;
            spd = Mathf.Round(spd);
            float walk_spd = target_player.GetWalkSpeed();
            float run_spd = target_player.GetRunSpeed();
            if(target_player.IsPlayerGrounded()){
                if(spd < walk_spd){
                    if(is_walk_sound_playing) StopWalkSound();
                    if(is_run_sound_playing) StopRunSound();
                }else if(walk_spd <= spd && spd < run_spd){
                    if(!is_walk_sound_playing) PlayWalkSound();
                    if(is_run_sound_playing) StopRunSound();
                }else if(run_spd <= spd){
                    if(is_walk_sound_playing) StopWalkSound();
                    if(!is_run_sound_playing) PlayRunSound();
                }
            }else{
                if(is_walk_sound_playing) StopWalkSound();
                if(is_run_sound_playing) StopRunSound();
            }
        }        
    }

    private void PlayRunSound(){
        run_sound.Play();
        is_run_sound_playing = true;
    }

    private void StopRunSound(){
        run_sound.Stop();
        is_run_sound_playing = false;
    }

    private void PlayWalkSound(){
        walk_sound.Play();
        is_walk_sound_playing = true;
    }

    private void StopWalkSound(){
        walk_sound.Stop();
        is_walk_sound_playing = false;
    }

    public override bool OnOwnershipRequest(VRCPlayerApi requestingPlayer, VRCPlayerApi requestedOwner){
        return false;
    }
}
GameReady

    public bool ConfirmEachLocalDataFoySyncOwner(){
        EachLocalDataForSync[] elds =  (EachLocalDataForSync[])eld_list.GetList();
        foreach(var eld in elds){               
            if(!eld.IsTargetPlayerBeOwner()) return false;
        }
        return true;
    }

No release unitypackage is available on the new repository

Describe the bug in detail:
There is no unitypackage in this repository's releases tab.

Provide steps/code to reproduce the bug:
Go to https://github.com/vrchat-community/UdonSharp/releases

Expected behavior:
The latest stable version of U# should be available as a unitypackage

Additional Information:
While they're still available at the old repository, having the old releases only available in the old repo is likely to lead to confusion.

Calling inbuilt functions on UdonBehaviours which do not have that function defined prevents transpilation

Describe the bug in detail:
Given method public override void OnPickupUseDown() { if (child) { child.OnPickupUseDown(); } }

When child is defined as public class Foo: UdonSharpBehaviour and Foo does not have public override void OnPickupUseDown() defined

Then the code fails to transpile.

Provide steps/code to reproduce the bug:
The given-when-then above should be clear enough.

In the above example, child is declared in the method's owning class as a public Foo.

Expected behavior:
The code transpiles.

Additional Information:
This seems to occur on most or all inbuilts.

Stack:

Assets/2022/Scripts/Syncer.cs(127,16): System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) [0x0001e] in <eae584ce26bc40229c1b1aa476bfa589>:0 at UdonSharp.Compiler.CompilationContext.GetUsbMethodLayout (UdonSharp.Compiler.Symbols.MethodSymbol method, UdonSharp.Compiler.AbstractPhaseContext context) [0x000ad] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\CompilationContext.cs:452 at UdonSharp.Compiler.Binder.BoundUdonSharpBehaviourInvocationExpression.EmitValue (UdonSharp.Compiler.Emit.EmitContext context) [0x000a3] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Binder\BoundNodes\BoundUdonSharpBehaviourInvocationExpression.cs:36 at UdonSharp.Compiler.Emit.EmitContext.EmitValue (UdonSharp.Compiler.Binder.BoundExpression expression) [0x00010] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Emit\EmitContext.cs:968 at UdonSharp.Compiler.Binder.BoundExpression.Emit (UdonSharp.Compiler.Emit.EmitContext context) [0x00001] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Binder\BoundNodes\BoundExpression.cs:35 at UdonSharp.Compiler.Emit.EmitContext.Emit (UdonSharp.Compiler.Binder.BoundNode node) [0x0001f] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Emit\EmitContext.cs:954 at UdonSharp.Compiler.Binder.BoundExpressionStatement.Emit (UdonSharp.Compiler.Emit.EmitContext context) [0x00001] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Binder\BoundNodes\BoundExpressionStatement.cs:19 at UdonSharp.Compiler.Emit.EmitContext.Emit (UdonSharp.Compiler.Binder.BoundNode node) [0x0001f] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Emit\EmitContext.cs:954 at UdonSharp.Compiler.Binder.BoundBlock.Emit (UdonSharp.Compiler.Emit.EmitContext context) [0x00023] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Binder\BoundNodes\BoundBlock.cs:30 at UdonSharp.Compiler.Emit.EmitContext.Emit (UdonSharp.Compiler.Binder.BoundNode node) [0x0001f] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Emit\EmitContext.cs:954 at UdonSharp.Compiler.Binder.BoundIfStatement.Emit (UdonSharp.Compiler.Emit.EmitContext context) [0x00041] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Binder\BoundNodes\BoundIfStatement.cs:32 at UdonSharp.Compiler.Emit.EmitContext.Emit (UdonSharp.Compiler.Binder.BoundNode node) [0x0001f] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Emit\EmitContext.cs:954 at UdonSharp.Compiler.Binder.BoundBlock.Emit (UdonSharp.Compiler.Emit.EmitContext context) [0x00023] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Binder\BoundNodes\BoundBlock.cs:30 at UdonSharp.Compiler.Emit.EmitContext.Emit (UdonSharp.Compiler.Binder.BoundNode node) [0x0001f] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Emit\EmitContext.cs:954 at UdonSharp.Compiler.Symbols.MethodSymbol.Emit (UdonSharp.Compiler.Emit.EmitContext context) [0x0009d] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Binder\Symbols\MethodSymbol.cs:244 at UdonSharp.Compiler.Symbols.UdonSharpBehaviourMethodSymbol.Emit (UdonSharp.Compiler.Emit.EmitContext context) [0x0011f] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Binder\Symbols\UdonSharpBehaviourMethodSymbol.cs:92 at UdonSharp.Compiler.Emit.EmitContext.Emit () [0x002ee] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\Emit\EmitContext.cs:186 at UdonSharp.Compiler.UdonSharpCompilerV1+<>c__DisplayClass24_0.<EmitAllPrograms>b__0 (System.ValueTuple`2[T1,T2] binding) [0x00144] in F:\VRChat Unity 2019\CC\SH1R\Assets\UdonSharp\Editor\Compiler\UdonSharpCompilerV1.cs:754

switch case default evaluation incorrect in 1.0.0b12

After updating to 1.0.0b12 from 0.20.3 on one of my old projects I found an issue with switch case statement evaluation order. Hopefully this is the right repo for the U# 1.0 beta

The default: case is being evaluated and short circuited when it's the first case. Meaning any case after the default case is effectively ignored. From what I can tell, this is only happening when it's the first case and when there are no other case labels on the case.

Conventionally in almost every switch statement I put the default case last, but in some of my code I put the default case first when it makes sense to order them as such and getting different behavior all of a sudden after updating was really sneaky!

Here's a simple demo script:

using UdonSharp;
using UnityEngine;

public class SwitchDefaultTest : UdonSharpBehaviour
{
    private int counter = 0;
    public override void Interact()
    {
        counter++;
        switch (counter % 3)
        {
            default:
                Debug.Log($"Default case - counter = {counter}");
                break;
            case 1:
                Debug.Log($"case 1 - counter = {counter}");
                    break;
            case 2:
                Debug.Log($"case 2 - counter = {counter}");
                break;
        }
    }

In 0.20.3 pressing the button repeatedly leads to all 3 cases being executed and logged appropriately.

2022.04.16 17:32:23 Log        -  case 1 - counter = 1
2022.04.16 17:32:24 Log        -  case 2 - counter = 2
2022.04.16 17:32:25 Log        -  Default case - counter = 3
2022.04.16 17:32:27 Log        -  case 1 - counter = 4
2022.04.16 17:32:28 Log        -  case 2 - counter = 5
2022.04.16 17:32:29 Log        -  Default case - counter = 6
2022.04.16 17:32:30 Log        -  case 1 - counter = 7
... etc

In 1.0.0b12 pressing the button always leads to the default case being executed and logged.

2022.04.16 17:39:03 Log        -  Default case - counter = 1
2022.04.16 17:39:03 Log        -  Default case - counter = 2
2022.04.16 17:39:04 Log        -  Default case - counter = 3
2022.04.16 17:39:04 Log        -  Default case - counter = 4
2022.04.16 17:39:04 Log        -  Default case - counter = 5
2022.04.16 17:39:05 Log        -  Default case - counter = 6
2022.04.16 17:39:05 Log        -  Default case - counter = 7

(An interesting thing I noticed was that adding a dummy case label to the demo script as follows it changes the behavior back to the expected default case behavior)

...
            default:
            case 9999999: // this added label can never be reached, but the default case now acts appropriately
                Debug.Log($"Default case - counter = {counter}");
                break;
...

Enum type parameters with a default value fail to compile.

Describe the bug in detail:
When a method takes an enum type as a parameter, and also gives it a default value, UdonSharp's compiler seems to forget that it is the same enum type being passed in. (System.ArgumentException: Type provided must be an Enum.)

Provide steps/code to reproduce the bug:
Declare an enum:

public enum MyEnum {
    MyFirstValue, MySecondValue
}

Declare a method with that enum type as a parameter and uses a default value:

public void MyMethod(MyEnum myEnumParameter = MyEnum.MyFirstValue) {
    // Method content
}

Call that method:

MyMethod(MyEnum.MySecondValue);

Expected behavior:
Program compiles and runs

Additional Information:
This was tested across behaviors. I did not actually test whether it happens within the same behavior.

Udonsharp Editor Error

Describe the bug in detail:
So the main Error I have been getting in Unity, when trying to put a new media player in, is something to do with Udon Sharp Editor, now its CsSharp, and some other things

Provide steps/code to reproduce the bug:
Just trying to add a Media player, Pro TV v 2.2 lastest update into the Suburban Lakehouse Package.

image
image
image

[1.1.2] Synced Enum types fail to compile

Describe the bug in detail:
After upgrading to 1.1.2, I am getting the following error type:
[UdonSharp] Packages/dev.architech.protv/Runtime/Core/TVManagerData.cs(17,42): Cannot sync type 'ArchiTech.ProTV.TVPlayState'
The TVPlayState is an enum and it compiles perfectly fine after downgrading back to 1.1.1

I think it has to do with this commit portion:
884e49b#diff-9d803f448d7a5ca806190f1f1f41999d4071c8d64a2f332679514ea838a3d19cR840

Provide steps/code to reproduce the bug:
Create an U# behaviour with an enum as a synced variable and run the compile.

Expected behavior:
Compiles correctly to an int.

Multiple instances of the same script share VRCUrl parameter value

This issue happens after migrating project through Creator Companion.

Describe the bug in detail:
If you add multiple instances of the same script anywhere in the scene they seem to share the VRCUrl type parameters and it's impossible to set them to different sets of these parameters.
This bug happens only if the field is declared with default value of VRCUrl.Empty.

Provide steps/code to reproduce the bug:
Tested with USharpVideo's PlayURLButton script, after setting up first button with URL1 adding second button with URL2 overwrites Url parameter in the first one with URL2.

Alternatively I'm providing sample scene and script to test this:
USharpSharedParametersIssue.unitypackage.zip
(try changing Url Bugged field and notice how it also changes on the other GameObject)

Cannot create jagged arrays from a generic method type

Describe the bug in detail:
When attempting to create a jagged array from a method generic it will initialize a single dimensional array containing the types provided through the generic. Attempting to then assign another array within the root array will result in an error.

EG: T[][] temp = new T[3][]; will actually just create T[] not T[][]

Provide steps/code to reproduce the bug:

ArrayHelper.cs

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

public static class ArrayHelper
{
    public static void JaggedArray<T>(ref T[][] jag, int rows, int cols) {
        jag = new T[rows][];
        for (int i = 0; i < rows; i++) {
            jag[i] = new T[cols];
        }
    }
}

UdonScript.cs

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class UdonScript : UdonSharpBehaviour
{
    private int[][] grid;
    
    void Start() {
        ArrayHelper.JaggedArray(ref grid, 7, 11);
    }
}

We can verify that this is generating the outcome described above by replacing jag[i] = new T[cols]; with Debug.Log(jag.GetType()); and see the outcome is System.Int32[]

Expected behavior:
The expected result in the provided steps to reproduce is ArrayHelper.JaggedArray method would initialize all the secondary arrays in the passed ref. And jag = new T[rows][]; would initialize a jagged array, not a 1d array.

Extra Details;
This has only been tested and verified with the Client Simulator for unity bundled with creator companion. I have not yet built/tested in VRChat.

MissingReferenceException: The variable sourceCsScript of UdonSharpProgramAsset doesn't exist anymore.

I'm getting this error spammed in my console 2 times a second and I can't find any "sourceCsScript" to reassign into that specific location.

Probably being stupid or blind, but any help would be greatly appreciated

MissingReferenceException: The variable sourceCsScript of UdonSharpProgramAsset doesn't exist anymore.
You probably need to reassign the sourceCsScript variable of the 'UdonSharpProgramAsset' script in the inspector.
UdonSharp.UdonSharpProgramAsset.GetClass () (at Packages/com.vrchat.udonsharp/Editor/UdonSharpProgramAsset.cs:482)
UdonSharp.Compiler.UdonSharpCompilerV1.Compile (UdonSharp.Compiler.UdonSharpCompileOptions options) (at Packages/com.vrchat.udonsharp/Editor/Compiler/UdonSharpCompilerV1.cs:302)
UdonSharp.UdonSharpProgramAsset.CompileAllCsPrograms (System.Boolean forceCompile, System.Boolean editorBuild) (at Packages/com.vrchat.udonsharp/Editor/UdonSharpProgramAsset.cs:295)
UdonSharpEditor.UdonSharpEditorManager.UpgradeAssetsIfNeeded () (at Packages/com.vrchat.udonsharp/Editor/UdonSharpEditorManager.cs:800)
UdonSharpEditor.UdonSharpEditorManager.OnEditorUpdate () (at Packages/com.vrchat.udonsharp/Editor/UdonSharpEditorManager.cs:744)
System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Delegate.DynamicInvokeImpl (System.Object[] args) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.MulticastDelegate.DynamicInvokeImpl (System.Object[] args) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Delegate.DynamicInvoke (System.Object[] args) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
UnityEditor.EditorApplication.Internal_CallUpdateFunctions () (at <a259d3c004024353a2c217da97495055>:0)

UdonSharp complains about not having any assemblies when there are no scripts in the project

Describe the bug in detail:
When I open the editor and there are no assemblies in the project, UdonSharp complains about not having assemblies when I've not clicked anything.

Provide steps/code to reproduce the bug:

  • Create new fresh project with VRChat SDK and UdonSharp
  • Close project
  • Reopen Project
  • Observe warning printed in console

Expected behavior:
Nothing gets printed to console because UdonSharp hasn't been manually invoked to compile scripts that aren't there.

Additional Information:
There should be a distinction between manually compiling all UdonSharp scripts, and when the editor/sdk decides it wants to check for script changes. If people manually tell UdonSharp to compile scripts and there are none, it should print this error, however, if people are just opening Unity, it should not.

VRCPlayerAPI happens a bug when I try to get force parameters of other players?

Behavior

I wrote a code to get parameters of all joining players, including position and force.
Something error happened when I try to get force parameters of other joining players, then all attached scripts will not work.
No error for obtaining positions only, in constrast.

I want to dump error log using try / catch semantics but it's not supported..

My code ( essential part )

I commented "HERE" in the corresponding line.

    // I allocate a memory for storing all players at begin
    private VRCPlayerApi [] _players = new VRCPlayerApi [ 64 ];
    private int _numPlayers = 0;

    void Update ()
    {
       // get number of players and their contexts
        _numPlayers = VRCPlayerApi.GetPlayerCount ();
        VRCPlayerApi.GetPlayers ( _players );
    }

    private void _debugMsg ()
    {
        // process for current joining players
        for ( int j=0; j<_numPlayers; j++ )
        {
            // get a current player
            VRCPlayerApi player = _players [ j ];
            if ( player == null ) continue;

            // get geometric parameters of the current player
            int id = player.playerId;
            UnityEngine.Vector3 pos = player.GetPosition ();
            UnityEngine.Vector3 vel = player.GetVelocity ();
            UnityEngine.Vector3 rot = player.GetRotation ().eulerAngles;

            // HERE: get force parameters of the current player
            // float walkSpeed = player.GetWalkSpeed ();
            // float runSpeed = player.GetRunSpeed ();
            // float sideWalkSpeed = player.GetStrafeSpeed ();
            // float jumpStrength = player.GetJumpImpulse ();
            // float gravityStrength = player.GetGravityStrength ();

            // do something

        }
    }

Environment

  • OS: Windows 11 Pro ( 64 bit )
  • Unity version: 2019.4.31f1
  • VRCSDK cersion: 3

When a class have "[UdonSynced,System.NonSerialized] public int[] apple", all sync value of the class don't be synced.

if a class have array value with System.NonSerialized or System.NonSerializedAttribute, all udonSynced value of the class can't synced.
if the value is not array, value is synced.

When [HideInInsplector], sync is work.

++enviroment:
u# 1.1
VRChat SKD 3.1.2
Workd SDK 3.1.2

++test code I used.

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using VRC.Udon.Common.Interfaces;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class BaseUserData : UdonSharpBehaviour
{
    [UdonSynced] public int test_a = -1;
}
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class EachLocalDataForSync : BaseUserData
{
    [UdonSynced] public int test_b = -1;    
    [UdonSynced,System.NonSerialized] public int[] apple;
    //[UdonSynced,System.NonSerialized] public int apple;
}
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class BaseUserDataList : UdonSharpBehaviour
{
    [SerializeField] BaseUserData[] target_list;

    public BaseUserData[] GetList(){
        return target_list;
    }
}

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class EachLocalDataForSyncList : BaseUserDataList
{

}

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using TMPro;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class Master : UdonSharpBehaviour
{
    [SerializeField] EachLocalDataForSyncList eld_list;
    [SerializeField] TextMeshProUGUI text;
    public void Set(){
        if(!Networking.LocalPlayer.isMaster){   
            General.OutLog("Not Master");
            return;
        }
        EachLocalDataForSync[] elds = (EachLocalDataForSync[])eld_list.GetList();
        int i = 0;
        foreach(var eld in elds){
            eld.test_a = i;
            eld.test_b = i;
            i += 1;
        }
    }

    public void Sync(){
        if(!Networking.LocalPlayer.isMaster){
            General.OutLog("Not Master");
            return;
        }
        EachLocalDataForSync[] elds = (EachLocalDataForSync[])eld_list.GetList();
        foreach(var eld in elds){
            eld.RequestSerialization();
        }
    }

    public void Log(){
        text.text = "Log()" + "\n" + text.text;
        EachLocalDataForSync[] elds = (EachLocalDataForSync[])eld_list.GetList();        
        int i = 0;
        foreach(var eld in elds){
            text.text = "ary_id : " + i.ToString() + "\n" + text.text;
            text.text = "test_a : " + eld.test_a.ToString() + "\n" + text.text;
            text.text = "test_b : " + eld.test_b.ToString() + "\n" + text.text;
             i += 1;
        }
    }
}

Recompile all UdonSharp programs on switching build platforms

Feature Description:
When switching, this would automatically re-compile all udonsharp programs after re-importing all assets. Plus this can cause users to forget to apply for PC/Quest platform and the programs still using the same settings as another build platform when not intended.

Additional context:
Just run the compiler on build switch after all assets load.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.