Project · Unity companions
Unity interaction rules companion
A complete portable C# project with 17 independent key, focus, range and invalid-input checks; no UnityEngine dependency.
All C# source files below are loaded together in the playground. Files written by a run live in its virtual directory.
Program.cs
using System;
public static class Program
{
public static void Main()
{
Console.WriteLine(InteractionChecks.Run() + " interaction checks passed");
}
}
Domain/GateState.cs
using System;
namespace SharpRune.InteractionRules
{
public sealed class GateState
{
public bool HasKey { get; private set; }
public bool Opened { get; private set; }
public void GrantKey() { if (!Opened) HasKey = true; }
public bool TryOpen(bool focused, float distance, float maximum)
{
if (maximum <= 0f || float.IsNaN(maximum) || float.IsInfinity(maximum)) throw new ArgumentOutOfRangeException(nameof(maximum));
if (distance < 0f || float.IsNaN(distance) || float.IsInfinity(distance)) throw new ArgumentOutOfRangeException(nameof(distance));
if (Opened || !HasKey || !focused || distance > maximum) return false;
HasKey = false; Opened = true; return true;
}
}
}
Checks/InteractionChecks.cs
using System;
using SharpRune.InteractionRules;
public static class InteractionChecks
{
public static int Run()
{
int passed = 0;
void Check(bool actual, string name)
{
if (!actual) throw new InvalidOperationException(name);
Console.WriteLine("PASS " + name); passed++;
}
bool Rejects(Action action)
{
try { action(); return false; }
catch (ArgumentOutOfRangeException) { return true; }
}
var gate = new GateState();
Check(!gate.HasKey && !gate.Opened, "fresh closed state");
Check(!gate.TryOpen(true, 1f, 3f) && !gate.Opened, "key required");
gate.GrantKey(); Check(gate.HasKey, "key grant");
Check(!gate.TryOpen(false, 1f, 3f) && gate.HasKey, "focus rejection preserves key");
Check(!gate.TryOpen(true, 3.01f, 3f) && gate.HasKey, "range rejection preserves key");
Check(gate.TryOpen(true, 3f, 3f) && gate.Opened && !gate.HasKey, "exact boundary consumes once");
Check(!gate.TryOpen(true, 1f, 3f), "opened state is idempotent");
gate.GrantKey(); Check(!gate.HasKey, "opened gate cannot regain key");
var other = new GateState(); other.GrantKey();
Check(!other.Opened && other.HasKey && gate.Opened, "instances independent");
Check(Rejects(() => other.TryOpen(true, -1f, 3f)) && other.HasKey && !other.Opened, "negative distance rejected unchanged");
Check(Rejects(() => other.TryOpen(true, float.NaN, 3f)), "NaN distance rejected");
Check(Rejects(() => other.TryOpen(true, float.PositiveInfinity, 3f)), "infinite distance rejected");
Check(Rejects(() => other.TryOpen(true, 1f, 0f)), "zero maximum rejected");
Check(Rejects(() => other.TryOpen(true, 1f, -1f)), "negative maximum rejected");
Check(Rejects(() => other.TryOpen(true, 1f, float.NaN)), "NaN maximum rejected");
Check(Rejects(() => other.TryOpen(true, 1f, float.PositiveInfinity)), "infinite maximum rejected");
Check(other.TryOpen(true, 0f, 3f) && !other.HasKey, "zero distance accepted");
return passed;
}
}
InteractionCompanion.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>9.0</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>