- SEO improvements: Updated package description, keywords, GitHub topics, and README front matter for discoverability
- Added Unity and MIT license badges to README
- Samples directory: Renamed
Samples/toSamples~/following Unity package convention. Samples are now hidden from the project and importable via Package Manager.
-
Attribute-Based Registration: Replaced
ServiceKitBehaviour<T>with non-genericServiceKitBehaviourand[Service]attribute- Services now use
[Service(typeof(IFoo))]attribute instead of generic inheritance - Enables multi-type registration:
[Service(typeof(IFoo), typeof(IBar))] - Concrete type fallback when no attribute provided
- Eliminates generic type parameter noise from class declarations and inheritance chains
- Services now use
-
InjectServicesAsyncdeprecated: Renamed toInject(). The old name still works but produces a compiler warning. -
API Renames (from v1.x):
Registered→IsServiceRegisteredReady→IsServiceReadyRegisterService()→RegisterServiceWithLocator()UnregisterService()→UnregisterServiceFromLocator()MarkServiceReady()→MarkServiceAsReady()OnServiceInjectionFailed()→HandleDependencyInjectionFailure()
-
Fluent Registration API: Chainable API for service registration
Register(service).As<IFoo>().As<IBar>().WithTags("core").Ready()- Supports multi-type registration, tags, and circular dependency exemption
-
InjectAsyncextension method: One-liner for dependency injectionawait locator.InjectAsync(this, destroyCancellationToken);- Applies default timeout, cancellation, and error handling automatically
-
Inject()builder alias: Shorter entry point for the fluent injection builderawait locator.Inject(this).WithTimeout(10f).ExecuteAsync();
-
TryResolveServiceatomic method: Race-condition-free 3-state service check- Returns
ServiceResolutionStatusenum:Ready,RegisteredNotReady, orNotRegistered - Single lock operation replaces the two-call
TryGetService+IsServiceRegisteredpattern
- Returns
-
[Service]attribute: Declarative service type registration- Supports multiple interface types per service
CircularDependencyExemptproperty for opting out of circular detection- Example:
[Service(typeof(IFoo), typeof(IBar), CircularDependencyExempt = true)]
-
ServiceKitBehaviournon-generic base class: For MonoBehaviour services- Reads
[Service]attribute via reflection (cached for performance) - Registers instance under all declared types
- Full lifecycle: Awake → Register → Inject → Init → Ready
UseLocator()method for unit testing with mocks
- Reads
-
Non-Generic Registration Methods: Added to
IServiceKitLocatorRegisterService(Type serviceType, object service, ...)RegisterServiceWithCircularExemption(Type serviceType, object service, ...)
-
Intelligent 3-State Optional Dependencies:
[InjectService(Required = false)]- Service ready → inject immediately
- Service registered but not ready → wait for it
- Service not registered → skip injection (field remains null)
-
Service Tags: Organize and filter services at runtime
AddTagsToService,RemoveTagsFromService,GetServiceTagsGetServicesWithTag,GetServicesWithAnyTag,GetServicesWithAllTags- Tags survive register-to-ready transitions
-
UniTask Integration: Automatic optimization when UniTask is available
- Zero-allocation async operations
- Conditional compilation via
SERVICEKIT_UNITASKdefine
-
Memory Performance Optimizations:
ServiceKitObjectPoolfor object pooling of Lists and StringBuilders- Zero-allocation service resolution for cached services
- Eliminated LINQ allocations in hot paths
-
Roslyn Analyzers (separate package):
- SK001:
[InjectService]field should be an interface type - SK002:
[InjectService]field should be private, non-static, non-readonly - SK003:
[Service(typeof(IFoo))]on a class that doesn't implementIFoo - SK004: Injection chain must include cancellation token
- SK005:
ServiceKitBehavioursubclass overridesAwake()without callingbase.Awake() - SK010: Prefer
ExecuteWithCancellationAsyncoverWithCancellation().ExecuteAsync()
- SK001:
-
Comprehensive Test Suite: 35+ tests covering race conditions, optional dependencies, tags, attribute reflection, multi-interface registration, and stress testing
-
ServiceKit Debug Window: Enhanced editor window
- Real-time service monitoring with readiness status
- Scene-based grouping with DontDestroyOnLoad separation
- Tag visualization and search/filtering
- Script navigation and GameObject pinging
- GetServiceAsync race condition: Task forwarding now set up inside lock
- Optional dependency race condition: Atomic
TryResolveServicereplaces non-atomic two-call check - UseLocator double-registration:
Interlocked.CompareExchangeguard prevents concurrent registration - Circular dependency string matching: Uses
Typereferences instead of string name comparison - DontDestroyOnLoad detection: Requires both scene name match and
buildIndex == -1 - Stack trace parsing: Scans by namespace instead of hardcoded frame index
- ObjectPool locking: Consistent locking across all pool types
- ServiceKitTimeoutManager: Proper cleanup on Play Mode exit and application quit
- TOCTOU race condition: Atomic
TryGetServicereplaces separate check-then-get - Awake order race condition: One-frame delay for optional dependencies allows all services to register
See the README.md for detailed migration instructions from v1.x to v2.0.
Releases have been renumbered for clarity. What was previously tagged as various 1.x and 2.x releases during development has been consolidated into two clean releases: 1.0.0 (the stable generic ServiceKitBehaviour<T> API) and 2.0.0 (the attribute-based [Service] API). All pre-1.0 tags remain in git history for reference.
The first stable release of ServiceKit, featuring:
ServiceKitBehaviour<T>generic base class for MonoBehaviour services- Two-phase lifecycle: Register → Ready with async dependency injection
[InjectService]attribute for field-based dependency injection- Intelligent 3-state optional dependencies: Ready → inject, registered → wait, absent → skip
- Circular dependency detection with path reporting and exemption support
- Service tags for runtime organization and filtering
- UniTask integration for zero-allocation async when available
- Fluent injection builder:
.WithTimeout().WithCancellation().ExecuteAsync() UseLocator()for unit testing with mock locators- ServiceKit Debug Window with scene-based grouping, search, and service inspection
- Addressables support for loading ServiceKitLocator assets on demand
- Memory-optimized object pooling for allocations
- Comprehensive test suite for race conditions and edge cases