| applyTo | **/*.cs |
|---|
JEngine is a Unity hot update framework using HybridCLR for runtime C# execution and YooAsset for resource management.
- Runtime code:
JEngine.CoreorJEngine.Core.* - Editor code:
JEngine.Core.EditororJEngine.Core.Editor.* - UI package:
JEngine.UI - Hot update code:
HotUpdate.Code - Exception:
Assets/Scripts/may contain user-level code without namespace (for user customization)
Always use UniTask instead of Task:
// Good
public async UniTask DoSomethingAsync() { }
// Bad
public async Task DoSomethingAsync() { }Document all public members:
/// <summary>
/// Description of what this does.
/// </summary>
public void MyMethod() { }Unity reloads the domain on recompile. Static state resets. For persistent state:
// Use SessionState for editor session persistence
SessionState.SetBool("MyKey", value);
bool value = SessionState.GetBool("MyKey", defaultValue);Always clean up ScriptableObjects and event handlers:
static MyClass()
{
EditorApplication.quitting += OnQuitting;
}
private static void OnQuitting()
{
EditorApplication.quitting -= OnQuitting;
if (_instance != null)
{
Object.Destroy(_instance);
_instance = null;
}
}For properties accessed from callbacks:
private static volatile bool _flag;
public static bool Flag => _flag;Three algorithms supported: XOR, AES, ChaCha20
- Config classes in
Runtime/Encrypt/Config/ - Bundle encryption in
Runtime/Encrypt/Bundle/ - Manifest encryption in
Runtime/Encrypt/Manifest/
public class MyConfig : ScriptableObject
{
private static MyConfig _instance;
public static MyConfig Instance => _instance ??= CreateInstance<MyConfig>();
}[InitializeOnLoad]
internal class MyEditorClass
{
static MyEditorClass()
{
// Runs on editor load and domain reload
}
}Unit tests are required for all non-core JEngine packages — i.e. any package under Packages/com.jasonxudeveloper.jengine.* except jengine.core. This includes JEngine.UI, JEngine.Util, and any future packages.
New features and new logic MUST include unit tests targeting 93%+ code coverage:
- All public methods, properties, and constructors
- Fluent API chaining
- Edge cases and error conditions
- Event handlers and callbacks (use reflection for private handlers)
- EditMode tests (
Tests/Editor/): Preferred for most logic — fast, no scene required. - PlayMode tests (
Tests/Runtime/): Use when the test needs a running game loop, MonoBehaviour lifecycle, or scene loading. PlayMode tests must run non-interactively (no user input, no manual scene setup). Use[UnityTest]withUniTask.ToCoroutine()for async PlayMode tests.
Tests mirror the source structure under each package's test folders:
Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Button/JButton.cs
→ Packages/com.jasonxudeveloper.jengine.ui/Tests/Editor/Components/Button/JButtonTests.cs
Packages/com.jasonxudeveloper.jengine.util/Runtime/JAction.cs
→ Packages/com.jasonxudeveloper.jengine.util/Tests/Editor/JActionTests.cs
# PlayMode tests when runtime behavior requires it:
Packages/com.jasonxudeveloper.jengine.util/Runtime/SomeFeature.cs
→ Packages/com.jasonxudeveloper.jengine.util/Tests/Runtime/SomeFeatureTests.cs
[TestFixture]
public class MyComponentTests
{
private MyComponent _component;
[SetUp]
public void SetUp()
{
_component = new MyComponent();
}
[Test]
public void Constructor_Default_AddsBaseClass()
{
Assert.IsTrue(_component.ClassListContains("my-component"));
}
}PlayMode tests must be fully automated — no interactive input or manual scene setup:
[TestFixture]
public class MyRuntimeTests
{
[UnityTest]
public IEnumerator MyAsyncTest() => UniTask.ToCoroutine(async () =>
{
var go = new GameObject();
var component = go.AddComponent<MyBehaviour>();
await UniTask.DelayFrame(1);
Assert.IsTrue(component.IsInitialized);
Object.Destroy(go);
});
}For private event handlers and internal styling methods:
var method = typeof(MyComponent).GetMethod("OnMouseEnter",
BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(_component, new object[] { null });
Assert.AreEqual(expectedColor, _component.style.backgroundColor.value);When reviewing JEngine code, check:
- UniTask usage (not Task)
- Domain reload handling in Editor code
- Resource cleanup (ScriptableObjects, events)
- Thread safety for callback-accessed state
- Proper namespace usage
- Unit tests with 93%+ coverage for new features/logic