update pos icon avatar in prefabs and update logic elsePlayerPortrait like hostPlayerPortrait

This commit is contained in:
CuongNV
2026-05-06 15:46:11 +07:00
parent a34993f531
commit 52925c000e
3 changed files with 71 additions and 20 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -151.8, y: 7.8005}
m_AnchoredPosition: {x: -151.8, y: -19.49}
m_SizeDelta: {x: 128, y: 180}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2085804573552353186
+2 -2
View File
@@ -637,8 +637,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_AnchoredPosition: {x: 0, y: -19}
m_SizeDelta: {x: 128, y: 180}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8158437551720672858
CanvasRenderer:
@@ -26,20 +26,27 @@ namespace BrewMonster
[Header("Portrait Stage")]
[Tooltip("Layer index for the Portrait layer (Project Settings > Tags and Layers).")]
[SerializeField] private int portraitLayer = 29;
[SerializeField] private int portraitLayer = 9;
[Tooltip("Fixed world position of the clone. Keep far from gameplay to avoid overlap.")]
[SerializeField] private Vector3 stagePosition = new Vector3(9999f, 0f, 0f);
[Header("Framing")]
[Tooltip("Distance from head focus point to camera.")]
[SerializeField] private float cameraDistance = 1.2f;
[Tooltip("Distance the camera sits in front of the face (meters). ~0.51.0 for tight portrait.")]
[SerializeField] private float cameraDistance = 0.7f;
[Tooltip("Height offset above stage origin used when head bone cannot be found.")]
[SerializeField] private float fallbackHeadHeight = 1.6f;
[Tooltip("Extra upward offset applied to the look-at focus point (moves portrait up toward eyes).")]
[SerializeField] private float faceUpLift = 0.04f;
[Tooltip("Slight horizontal angle so the portrait isn't perfectly front-on (degrees).")]
[SerializeField][Range(0f, 45f)] private float horizontalAngleDeg = 15f;
[Tooltip("How fast the camera rotation interpolates toward the face each frame (higher = snappier).")]
[SerializeField][Range(1f, 50f)] private float lookSmoothSpeed = 20f;
[Header("Head Bone Face Direction")]
[Tooltip("Which local axis of Bip01 Head points OUT of the face (toward the camera).")]
[SerializeField] private FaceAxis headFaceAxis = FaceAxis.Forward;
[Tooltip("Flip the chosen face axis (e.g. if Forward gives back-of-head, enable this).")]
[SerializeField] private bool flipFaceAxis;
[SerializeField][Range(10f, 60f)] private float fieldOfView = 35f;
@@ -88,6 +95,7 @@ namespace BrewMonster
}
_portraitClone = Object.Instantiate(modelRoot.gameObject);
_portraitClone.GetComponentInChildren<Animator>().enabled = false;
_portraitClone.name = "[Portrait] ElsePlayer";
_portraitClone.transform.position = stagePosition;
_portraitClone.transform.rotation = Quaternion.identity;
@@ -100,7 +108,7 @@ namespace BrewMonster
_headBone = PortraitCaptureUtils.FindHeadBone(_portraitClone.transform);
PositionCamera();
AttachCameraToHeadBone();
SetCameraEnabled(true);
}
@@ -115,27 +123,68 @@ namespace BrewMonster
Object.Destroy(_portraitClone);
_portraitClone = null;
}
DetachCamera();
_headBone = null;
SetCameraEnabled(false);
}
private void LateUpdate()
{
if (portraitCamera == null || !portraitCamera.enabled) return;
if (_headBone == null) return;
Vector3 faceCenter = _headBone.position + Vector3.up * faceUpLift;
Vector3 toFace = faceCenter - portraitCamera.transform.position;
if (toFace.sqrMagnitude < 0.0001f) return;
Quaternion targetRot = Quaternion.LookRotation(toFace);
portraitCamera.transform.rotation = Quaternion.Slerp(
portraitCamera.transform.rotation,
targetRot,
Time.deltaTime * lookSmoothSpeed);
}
// ──────────────────────────────────────────────────────────────────────────────
// Internal
// ──────────────────────────────────────────────────────────────────────────────
private void PositionCamera()
private void AttachCameraToHeadBone()
{
if (portraitCamera == null) return;
Vector3 focusPoint = _headBone != null
? _headBone.position
: stagePosition + Vector3.up * fallbackHeadHeight;
Transform anchor = _headBone != null ? _headBone : _portraitClone.transform;
Vector3 faceDir = GetFaceDirectionWorld(anchor);
Vector3 headPos = anchor.position;
Vector3 faceCenter = headPos + Vector3.up * faceUpLift;
Vector3 camWorldPos = headPos + faceDir * cameraDistance;
float rad = horizontalAngleDeg * Mathf.Deg2Rad;
Vector3 offset = new Vector3(Mathf.Sin(rad) * cameraDistance, 0f, -cameraDistance);
portraitCamera.transform.SetParent(anchor, worldPositionStays: false);
portraitCamera.transform.position = camWorldPos;
portraitCamera.transform.LookAt(faceCenter);
}
portraitCamera.transform.position = focusPoint + offset;
portraitCamera.transform.LookAt(focusPoint);
private Vector3 GetFaceDirectionWorld(Transform bone)
{
Vector3 dir = headFaceAxis switch
{
FaceAxis.Forward => bone.forward,
FaceAxis.Back => -bone.forward,
FaceAxis.Up => bone.up,
FaceAxis.Down => -bone.up,
FaceAxis.Right => bone.right,
FaceAxis.Left => -bone.right,
_ => bone.forward
};
return flipFaceAxis ? -dir : dir;
}
private void DetachCamera()
{
if (portraitCamera != null)
{
portraitCamera.transform.SetParent(transform, worldPositionStays: false);
SetCameraEnabled(false);
}
}
private void SetCameraEnabled(bool enabled)
@@ -166,5 +215,7 @@ namespace BrewMonster
}
outputTexture = PortraitCaptureUtils.CreatePortraitRT("ElsePlayerPortraitRT", portraitCamera);
}
public enum FaceAxis { Forward, Back, Up, Down, Right, Left }
}
}