Implement seamless physical Screen Wrapping using Compound Collider on wrap visuals container
Подробный список изменений: - Объект wrapVisualCloneRoot сделан дочерним к transform игрока. - Внедрен метод RebuildWrapCollider для автоматического дублирования основного коллайдера игрока (Box/Circle/Capsule) на wrapVisualCloneRoot. - В Unity дочерние коллайдеры при наличии Rigidbody2D на родителе автоматически формируют Compound Collider (составное физическое тело). Это позволило собирать монеты, активировать пружины и получать урон от врагов визуальным клоном на противоположной стороне экрана. - В методе CopyWrappedVisuals сменено позиционирование клонов SpriteRenderer на локальные координаты для предотвращения графических артефактов при переносе.
This commit is contained in:
parent
988f54bc01
commit
77c72e2f01
@ -1588,13 +1588,23 @@ namespace DanroJump.Gameplay
|
||||
sourceRenderers.Clear();
|
||||
wrapRendererClones.Clear();
|
||||
|
||||
if (visualRoot != null)
|
||||
if (wrapVisualCloneRoot == null)
|
||||
{
|
||||
sourceRenderers.AddRange(visualRoot.GetComponentsInChildren<SpriteRenderer>(true));
|
||||
wrapVisualCloneRoot = new GameObject($"{name} Wrap Visuals").transform;
|
||||
wrapVisualCloneRoot.SetParent(transform, false);
|
||||
wrapVisualCloneRoot.gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
|
||||
var allRenderers = visualRoot != null
|
||||
? visualRoot.GetComponentsInChildren<SpriteRenderer>(true)
|
||||
: GetComponentsInChildren<SpriteRenderer>(true);
|
||||
|
||||
foreach (var r in allRenderers)
|
||||
{
|
||||
sourceRenderers.AddRange(GetComponentsInChildren<SpriteRenderer>(true));
|
||||
if (r != null && (wrapVisualCloneRoot == null || !r.transform.IsChildOf(wrapVisualCloneRoot)))
|
||||
{
|
||||
sourceRenderers.Add(r);
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceRenderers.Count == 0)
|
||||
@ -1602,12 +1612,6 @@ namespace DanroJump.Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
if (wrapVisualCloneRoot == null)
|
||||
{
|
||||
wrapVisualCloneRoot = new GameObject($"{name} Wrap Visuals").transform;
|
||||
wrapVisualCloneRoot.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
for (var index = sourceRenderers.Count - 1; index >= 0; index--)
|
||||
{
|
||||
var sourceRenderer = sourceRenderers[index];
|
||||
@ -1621,6 +1625,59 @@ namespace DanroJump.Gameplay
|
||||
clone.transform.SetParent(wrapVisualCloneRoot, false);
|
||||
wrapRendererClones.Insert(0, clone);
|
||||
}
|
||||
|
||||
RebuildWrapCollider();
|
||||
}
|
||||
|
||||
private void RebuildWrapCollider()
|
||||
{
|
||||
if (wrapVisualCloneRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var oldColliders = wrapVisualCloneRoot.GetComponents<Collider2D>();
|
||||
foreach (var old in oldColliders)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
Destroy(old);
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyImmediate(old);
|
||||
}
|
||||
}
|
||||
|
||||
var sourceCollider = GetComponent<Collider2D>();
|
||||
if (sourceCollider != null)
|
||||
{
|
||||
if (sourceCollider is BoxCollider2D boxCol)
|
||||
{
|
||||
var cloneCol = wrapVisualCloneRoot.gameObject.AddComponent<BoxCollider2D>();
|
||||
cloneCol.size = boxCol.size;
|
||||
cloneCol.offset = boxCol.offset;
|
||||
cloneCol.isTrigger = boxCol.isTrigger;
|
||||
cloneCol.sharedMaterial = boxCol.sharedMaterial;
|
||||
}
|
||||
else if (sourceCollider is CircleCollider2D circleCol)
|
||||
{
|
||||
var cloneCol = wrapVisualCloneRoot.gameObject.AddComponent<CircleCollider2D>();
|
||||
cloneCol.radius = circleCol.radius;
|
||||
cloneCol.offset = circleCol.offset;
|
||||
cloneCol.isTrigger = circleCol.isTrigger;
|
||||
cloneCol.sharedMaterial = circleCol.sharedMaterial;
|
||||
}
|
||||
else if (sourceCollider is CapsuleCollider2D capsuleCol)
|
||||
{
|
||||
var cloneCol = wrapVisualCloneRoot.gameObject.AddComponent<CapsuleCollider2D>();
|
||||
cloneCol.size = capsuleCol.size;
|
||||
cloneCol.offset = capsuleCol.offset;
|
||||
cloneCol.direction = capsuleCol.direction;
|
||||
cloneCol.isTrigger = capsuleCol.isTrigger;
|
||||
cloneCol.sharedMaterial = capsuleCol.sharedMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1660,11 +1717,13 @@ namespace DanroJump.Gameplay
|
||||
CopyWrappedVisuals(new Vector3(wrapOffsetX, 0f, 0f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Копирует состояние исходных SpriteRenderer в wrap-клоны.
|
||||
/// </summary>
|
||||
private void CopyWrappedVisuals(Vector3 offset)
|
||||
{
|
||||
if (wrapVisualCloneRoot != null)
|
||||
{
|
||||
wrapVisualCloneRoot.localPosition = offset;
|
||||
}
|
||||
|
||||
for (var index = 0; index < sourceRenderers.Count; index++)
|
||||
{
|
||||
var source = sourceRenderers[index];
|
||||
@ -1694,8 +1753,9 @@ namespace DanroJump.Gameplay
|
||||
clone.sortingLayerID = source.sortingLayerID;
|
||||
clone.sortingOrder = source.sortingOrder;
|
||||
clone.sharedMaterial = source.sharedMaterial;
|
||||
clone.transform.SetPositionAndRotation(source.transform.position + offset, source.transform.rotation);
|
||||
clone.transform.localScale = source.transform.lossyScale;
|
||||
clone.transform.localPosition = source.transform.localPosition;
|
||||
clone.transform.localRotation = source.transform.localRotation;
|
||||
clone.transform.localScale = source.transform.localScale;
|
||||
clone.gameObject.layer = source.gameObject.layer;
|
||||
}
|
||||
catch (MissingReferenceException)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user