Prefer provider-authored shot effects
This commit is contained in:
parent
0c817dbffa
commit
e5a43cffcd
4 changed files with 117 additions and 15 deletions
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
#nullable enable
|
||||
|
|
@ -20,6 +21,7 @@ namespace GameCult.Eve.UnityScene
|
|||
private Material? _material;
|
||||
|
||||
public int ActiveTrajectoryCount => _active.Count;
|
||||
public int ActiveFallbackTrajectoryCount => _active.Count(trajectory => trajectory.Line != null);
|
||||
|
||||
public void Bind(EveUnityPlayableWorldClientHost host, IEveUnityGameObjectAssetProvider? assetProvider = null)
|
||||
{
|
||||
|
|
@ -43,19 +45,10 @@ namespace GameCult.Eve.UnityScene
|
|||
if (receipt == null) throw new ArgumentNullException(nameof(receipt));
|
||||
var shot = new GameObject("Eve shot " + receipt.ShotId);
|
||||
shot.transform.SetParent(transform, false);
|
||||
var line = shot.AddComponent<LineRenderer>();
|
||||
line.useWorldSpace = true;
|
||||
line.positionCount = 2;
|
||||
var intensityScale = Mathf.Clamp(Mathf.Sqrt((float)receipt.PresentationIntensity), 0.5f, 4f);
|
||||
line.startWidth = Math.Max(0.01f, width * intensityScale);
|
||||
line.endWidth = Math.Max(0.01f, width * 0.5f * intensityScale);
|
||||
line.material = SharedMaterial();
|
||||
line.startColor = line.endColor = receipt.Hit ? hitColor : missColor;
|
||||
|
||||
var origin = Vector(receipt.Origin);
|
||||
line.SetPosition(0, origin);
|
||||
var endpoint = Vector(receipt.Endpoint);
|
||||
var effectPrefab = ResolveEffectPrefab(receipt);
|
||||
LineRenderer? line = null;
|
||||
if (effectPrefab != null)
|
||||
{
|
||||
var effect = Instantiate(effectPrefab, shot.transform);
|
||||
|
|
@ -71,10 +64,23 @@ namespace GameCult.Eve.UnityScene
|
|||
lightning.StartAnimation();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
line = shot.AddComponent<LineRenderer>();
|
||||
line.useWorldSpace = true;
|
||||
line.positionCount = 2;
|
||||
var intensityScale = Mathf.Clamp(Mathf.Sqrt((float)receipt.PresentationIntensity), 0.5f, 4f);
|
||||
line.startWidth = Math.Max(0.01f, width * intensityScale);
|
||||
line.endWidth = Math.Max(0.01f, width * 0.5f * intensityScale);
|
||||
line.material = SharedMaterial();
|
||||
line.startColor = line.endColor = receipt.Hit ? hitColor : missColor;
|
||||
line.SetPosition(0, origin);
|
||||
}
|
||||
var impactPrefab = ResolveRolePrefab("effect.impact." + receipt.ImpactKind);
|
||||
var travels = string.Equals(receipt.PresentationKind, "bolt", StringComparison.Ordinal) ||
|
||||
string.Equals(receipt.PresentationKind, "guided", StringComparison.Ordinal);
|
||||
line.SetPosition(1, travels ? origin : endpoint);
|
||||
if (line != null)
|
||||
line.SetPosition(1, travels ? origin : endpoint);
|
||||
_active.Add(new ActiveTrajectory(
|
||||
shot,
|
||||
line,
|
||||
|
|
@ -93,7 +99,7 @@ namespace GameCult.Eve.UnityScene
|
|||
{
|
||||
var trajectory = _active[index];
|
||||
var progress = Mathf.Clamp01((now - trajectory.StartedAt) / trajectory.Duration);
|
||||
if (trajectory.Travels)
|
||||
if (trajectory.Travels && trajectory.Line != null)
|
||||
trajectory.Line.SetPosition(1, Vector3.Lerp(trajectory.Origin, trajectory.Endpoint, progress));
|
||||
if (progress >= 1 && !trajectory.ImpactPresented)
|
||||
{
|
||||
|
|
@ -146,7 +152,7 @@ namespace GameCult.Eve.UnityScene
|
|||
|
||||
private sealed class ActiveTrajectory
|
||||
{
|
||||
public ActiveTrajectory(GameObject root, LineRenderer line, Vector3 origin, Vector3 endpoint, float startedAt, float duration, bool travels, GameObject? impactPrefab)
|
||||
public ActiveTrajectory(GameObject root, LineRenderer? line, Vector3 origin, Vector3 endpoint, float startedAt, float duration, bool travels, GameObject? impactPrefab)
|
||||
{
|
||||
Root = root;
|
||||
Line = line;
|
||||
|
|
@ -159,7 +165,7 @@ namespace GameCult.Eve.UnityScene
|
|||
}
|
||||
|
||||
public GameObject Root { get; }
|
||||
public LineRenderer Line { get; }
|
||||
public LineRenderer? Line { get; }
|
||||
public Vector3 Origin { get; }
|
||||
public Vector3 Endpoint { get; }
|
||||
public float StartedAt { get; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace GameCult.Eve.UnityScene.Tests
|
||||
{
|
||||
public sealed class EveUnityShotTrajectoryRendererTests
|
||||
{
|
||||
[Test]
|
||||
public void ProviderShotEffectReplacesGenericFallbackLine()
|
||||
{
|
||||
var root = new GameObject("shot-renderer-provider-test");
|
||||
var prefab = new GameObject("provider-bolt");
|
||||
try
|
||||
{
|
||||
var host = root.AddComponent<EveUnityPlayableWorldClientHost>();
|
||||
var renderer = root.AddComponent<EveUnityShotTrajectoryRenderer>();
|
||||
renderer.Bind(host, new BoltProvider(prefab));
|
||||
|
||||
renderer.Present(Shot("provider-shot"));
|
||||
|
||||
Assert.That(renderer.ActiveTrajectoryCount, Is.EqualTo(1));
|
||||
Assert.That(renderer.ActiveFallbackTrajectoryCount, Is.Zero);
|
||||
Assert.That(root.GetComponentsInChildren<LineRenderer>(), Is.Empty);
|
||||
Assert.That(root.transform.GetChild(0).Find("provider-bolt(Clone)"), Is.Not.Null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(root);
|
||||
UnityEngine.Object.DestroyImmediate(prefab);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MissingProviderShotEffectUsesGenericFallbackLine()
|
||||
{
|
||||
var root = new GameObject("shot-renderer-fallback-test");
|
||||
try
|
||||
{
|
||||
var host = root.AddComponent<EveUnityPlayableWorldClientHost>();
|
||||
var renderer = root.AddComponent<EveUnityShotTrajectoryRenderer>();
|
||||
renderer.Bind(host, new BoltProvider(null));
|
||||
|
||||
renderer.Present(Shot("fallback-shot"));
|
||||
|
||||
Assert.That(renderer.ActiveTrajectoryCount, Is.EqualTo(1));
|
||||
Assert.That(renderer.ActiveFallbackTrajectoryCount, Is.EqualTo(1));
|
||||
Assert.That(root.GetComponentsInChildren<LineRenderer>(), Has.Length.EqualTo(1));
|
||||
}
|
||||
finally
|
||||
{
|
||||
UnityEngine.Object.DestroyImmediate(root);
|
||||
}
|
||||
}
|
||||
|
||||
private static EveUnityShotReceipt Shot(string id) =>
|
||||
new EveUnityShotReceipt(new EveUnitySceneNode(id, "shot.receipt", "scene-node",
|
||||
new Dictionary<string, string>(StringComparer.Ordinal)
|
||||
{
|
||||
["shotId"] = id,
|
||||
["origin"] = "0,0",
|
||||
["endpoint"] = "10,0",
|
||||
["presentationDuration"] = "0.2",
|
||||
["presentationKind"] = "bolt",
|
||||
["impactKind"] = "armor",
|
||||
["presentationIntensity"] = "85",
|
||||
["hit"] = "true"
|
||||
}, Empty(), Empty(), 0, 0, Array.Empty<EveUnitySceneEmbeddedDocumentSlot>(), null,
|
||||
Array.Empty<EveUnitySceneNode>()));
|
||||
|
||||
private static IReadOnlyDictionary<string, string> Empty() =>
|
||||
new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
|
||||
private sealed class BoltProvider : IEveUnityGameObjectAssetProvider
|
||||
{
|
||||
private readonly GameObject? _prefab;
|
||||
public BoltProvider(GameObject? prefab) { _prefab = prefab; }
|
||||
public GameObject? ResolvePrefab(EveUnityPlayableWorldAssetBinding asset) =>
|
||||
asset.EntityKind == "effect.shot.bolt" ? _prefab : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a1d80f8e29164e23ad367feefb67c49e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "org.gamecult.eve.unity-scene",
|
||||
"displayName": "Eve Unity Scene Lowering",
|
||||
"version": "0.3.19",
|
||||
"version": "0.3.20",
|
||||
"unity": "2021.3",
|
||||
"description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.",
|
||||
"dependencies": {
|
||||
|
|
|
|||
Reference in a new issue