2025-02-14 13:20:54 +08:00
using DG.Tweening ;
2025-02-08 16:22:00 +08:00
using UnityEngine ;
using UnityEngine.EventSystems ;
public class Show3DCamera : MonoBehaviour
{
2025-02-10 10:54:47 +08:00
public Vector3 targetPos ; // Χ <> <CEA7> <EFBFBD> <EFBFBD> ת<EFBFBD> <D7AA> Ŀ<EFBFBD> <C4BF> <EFBFBD> <EFBFBD>
2025-03-17 17:21:06 +08:00
public float rotateSpeed ; // <20> <> ת<EFBFBD> ٶ<EFBFBD>
2025-03-11 13:04:58 +08:00
public float moveSpeed ; // <20> ƶ<EFBFBD> <C6B6> ٶ<EFBFBD>
public float distance ; // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ŀ<EFBFBD> <C4BF> <EFBFBD> ľ<EFBFBD> <C4BE> <EFBFBD>
2025-03-17 17:21:06 +08:00
public float distanceMin ;
public float distanceMax ;
2025-03-11 13:04:58 +08:00
public Vector2 pitchMinMax /* = new Vector2(-20, 80)*/ ; // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ƿ<EFBFBD> Χ
2025-02-08 16:22:00 +08:00
private Vector3 offset ; // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ŀ<EFBFBD> <C4BF> <EFBFBD> <EFBFBD> ƫ<EFBFBD> <C6AB> <EFBFBD> <EFBFBD>
private float yaw = 0f ; // ƫ<> <C6AB> <EFBFBD> ǣ<EFBFBD> <C7A3> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ת<EFBFBD> <D7AA>
private float pitch = 0f ; // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ǣ<EFBFBD> <C7A3> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ת<EFBFBD> <D7AA>
public static Show3DCamera instance ;
2025-02-10 10:54:47 +08:00
RectTransform inputRect ;
2025-02-08 16:22:00 +08:00
Camera self ;
2025-02-10 10:54:47 +08:00
private GameObject lastHitObject = null ;
2025-02-13 17:21:18 +08:00
public RenderTexture texture ;
public bool lockMove = false ;
2025-02-14 13:20:54 +08:00
private Vector2 mouseDownPosition ; // <20> <> ¼<EFBFBD> <C2BC> <EFBFBD> 갴<EFBFBD> <EAB0B4> ʱ<EFBFBD> <CAB1> λ<EFBFBD> <CEBB>
2025-03-17 17:21:06 +08:00
public enum RotationType
{
Orbit , // ԭ<> <D4AD> <EFBFBD> <EFBFBD> ʽ <EFBFBD> <CABD> ת
Spherical // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ת
}
public RotationType type = RotationType . Orbit ;
Transform target ;
Vector3 targetPosition ;
Vector3 targetRotate ;
2025-02-08 16:22:00 +08:00
private void Awake ( )
{
instance = this ;
self = transform . GetComponent < Camera > ( ) ;
DontDestroyOnLoad ( this ) ;
2025-02-08 17:33:21 +08:00
gameObject . SetActive ( false ) ;
2025-02-08 16:22:00 +08:00
}
2025-02-13 17:21:18 +08:00
2025-02-14 13:20:54 +08:00
public void Set ( Transform target , float rotateSpeed = 10 , float moveSpeed = 0.1f , float distance = 0.1f , float pitchMin = - 20 , float pitchMax = 80 , float distanceMin = 0.2f , float distanceMax = 20f , RectTransform inputRect = null , bool isRenderTexture = true , float moveTime = - 1 )
2025-02-08 16:22:00 +08:00
{
if ( target = = null )
{
Debug . LogError ( "Target is not assigned!" ) ;
return ;
}
2025-02-10 10:54:47 +08:00
2025-03-17 17:21:06 +08:00
this . target = target ;
this . targetPosition = target . position ;
this . targetRotate = target . eulerAngles ;
2025-02-08 16:22:00 +08:00
yaw = 0 ;
pitch = 0 ;
2025-03-11 13:14:12 +08:00
// <20> <> ʼ <EFBFBD> <CABC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> <CEBB>
2025-02-10 10:54:47 +08:00
this . inputRect = inputRect ;
this . targetPos = target . transform . position ;
2025-03-11 13:14:12 +08:00
//this.rotateSpeed = rotateSpeed;
//this.moveSpeed = moveSpeed;
//this.distance = distance;
//this.distanceMin = distanceMin;
//this.distanceMax = distanceMax;
//this.pitchMinMax = new Vector2(pitchMin, pitchMax);
2025-02-08 16:22:00 +08:00
// <20> <> ʼ <EFBFBD> <CABC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> <CEBB>
offset = new Vector3 ( 0 , 0 , - distance ) ;
2025-02-13 17:21:18 +08:00
if ( isRenderTexture )
{
self . targetTexture = texture ;
}
else
{
self . targetTexture = null ;
}
2025-02-14 13:20:54 +08:00
UpdateCameraPosition ( moveTime ) ;
2025-02-08 16:22:00 +08:00
}
2025-02-10 10:54:47 +08:00
2025-02-08 16:22:00 +08:00
2025-03-11 14:37:17 +08:00
public void ResetCamera ( Transform target , RectTransform inputRect = null , bool isRenderTexture = false )
2025-03-11 13:59:38 +08:00
{
if ( target = = null )
{
Debug . LogError ( "Target is not assigned!" ) ;
return ;
}
2025-03-17 17:21:06 +08:00
this . target = target ;
this . targetPosition = target . position ;
this . targetRotate = target . eulerAngles ;
2025-03-11 13:59:38 +08:00
yaw = 0 ;
pitch = 0 ;
// <20> <> ʼ <EFBFBD> <CABC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> <CEBB>
this . inputRect = inputRect ;
this . targetPos = target . transform . position ;
// <20> <> ʼ <EFBFBD> <CABC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> <CEBB>
offset = new Vector3 ( 0 , 0 , - distance ) ;
if ( isRenderTexture )
{
self . targetTexture = texture ;
}
else
{
self . targetTexture = null ;
}
UpdateCameraPosition ( - 1 ) ;
}
2025-02-08 16:22:00 +08:00
void Update ( )
{
2025-02-14 13:20:54 +08:00
if ( targetPos ! = null & & lockMove = = false & & EventSystem . current . IsPointerOverGameObject ( ) = = false )
2025-02-08 16:22:00 +08:00
{
2025-03-17 17:21:06 +08:00
2025-02-14 13:20:54 +08:00
if ( Input . GetMouseButtonDown ( 0 ) )
{
// <20> <> ¼<EFBFBD> <C2BC> <EFBFBD> 갴<EFBFBD> <EAB0B4> ʱ<EFBFBD> <CAB1> λ<EFBFBD> <CEBB>
mouseDownPosition = Input . mousePosition ;
}
2025-02-08 16:22:00 +08:00
// <20> <> ס <EFBFBD> <D7A1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ʱ<EFBFBD> <CAB1> ת<EFBFBD> <D7AA> <EFBFBD> <EFBFBD>
if ( Input . GetMouseButton ( 0 ) )
{
2025-02-14 13:20:54 +08:00
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> 갴<EFBFBD> º<EFBFBD> ̧<EFBFBD> <CCA7> λ<EFBFBD> <CEBB> ֮<EFBFBD> <D6AE> <EFBFBD> ľ<EFBFBD> <C4BE> <EFBFBD>
float distance = Vector2 . Distance ( mouseDownPosition , Input . mousePosition ) ;
if ( distance > 1f )
{
RotateCamera ( ) ;
}
2025-02-08 16:22:00 +08:00
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
float scroll = Input . GetAxis ( "Mouse ScrollWheel" ) ;
if ( scroll ! = 0 )
{
ZoomCamera ( scroll ) ;
}
// <20> <> ס <EFBFBD> <D7A1> <EFBFBD> <EFBFBD> <EFBFBD> Ҽ<EFBFBD> ʱ<EFBFBD> ƶ<EFBFBD> Ŀ<EFBFBD> <C4BF> <EFBFBD> <EFBFBD>
if ( Input . GetMouseButton ( 1 ) )
{
MoveTarget ( ) ;
}
DetectHoveredObject ( ) ;
}
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ͣ<EFBFBD> <CDA3> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
2025-02-10 10:54:47 +08:00
public void DetectHoveredObject ( )
2025-02-08 16:22:00 +08:00
{
2025-02-10 10:54:47 +08:00
GameObject obj = null ;
Vector2 mousePosition = Input . mousePosition ;
if ( inputRect ! = null )
2025-02-08 16:22:00 +08:00
{
2025-02-10 10:54:47 +08:00
var pos = ( mousePosition - ( Vector2 ) inputRect . position ) / inputRect . lossyScale - inputRect . rect . position ;
mousePosition = pos / inputRect . rect . size ;
2025-02-08 16:22:00 +08:00
}
2025-02-10 10:54:47 +08:00
var ray = self . ViewportPointToRay ( mousePosition ) ;
RaycastHit raycastHit ;
if ( Physics . Raycast ( ray , out raycastHit ) )
{
//Debug.Log(raycastHit.transform.name);
obj = raycastHit . transform . gameObject ;
2025-02-08 16:22:00 +08:00
2025-02-10 10:54:47 +08:00
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> е <EFBFBD> <D0B5> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> һ <EFBFBD> λ<EFBFBD> <CEBB> е <EFBFBD> <D0B5> <EFBFBD> <EFBFBD> 岻ͬ<E5B2BB> <CDAC> <EFBFBD> <EFBFBD> ʾ <EFBFBD> <CABE> <EFBFBD> ߽<EFBFBD> <DFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
if ( obj ! = lastHitObject )
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ¼<EFBFBD>
OnMouseEnterObj ( obj ) ;
2025-02-08 16:22:00 +08:00
2025-02-10 10:54:47 +08:00
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> һ <EFBFBD> λ<EFBFBD> <CEBB> е <EFBFBD> <D0B5> <EFBFBD> <EFBFBD> 岻Ϊ<E5B2BB> գ <EFBFBD> <D5A3> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> 뿪<EFBFBD> ¼<EFBFBD>
if ( lastHitObject ! = null & & lastHitObject ! = obj )
{
OnMouseExitObj ( lastHitObject ) ;
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> һ <EFBFBD> λ<EFBFBD> <CEBB> е <EFBFBD> <D0B5> <EFBFBD> <EFBFBD> <EFBFBD>
lastHitObject = obj ;
}
2025-02-08 16:22:00 +08:00
2025-02-10 10:54:47 +08:00
}
}
else
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> û<EFBFBD> л<EFBFBD> <D0BB> <EFBFBD> <EFBFBD> κ<EFBFBD> <CEBA> <EFBFBD> <EFBFBD> 壬<EFBFBD> <E5A3AC> <EFBFBD> <EFBFBD> һ <EFBFBD> λ<EFBFBD> <CEBB> е <EFBFBD> <D0B5> <EFBFBD> <EFBFBD> 岻Ϊ<E5B2BB> գ <EFBFBD> <D5A3> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> 뿪<EFBFBD> ¼<EFBFBD>
if ( lastHitObject ! = null )
{
OnMouseExitObj ( lastHitObject ) ;
lastHitObject = null ;
}
}
2025-02-08 16:22:00 +08:00
}
2025-02-14 13:20:54 +08:00
/// <summary>
/// <20> ۽<EFBFBD> ij<EFBFBD> <C4B3> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
/// </summary>
2025-02-14 17:09:41 +08:00
public void FocusObj ( Vector3 target , float distance = 1f , float moveTime = - 1 )
2025-02-14 13:20:54 +08:00
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ǰ<EFBFBD> <C7B0> һ <EFBFBD> <D2BB> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> ã<EFBFBD> <C3A3> <EFBFBD> ΪCube<62> <65> Ŀ<EFBFBD> <C4BF> λ<EFBFBD> <CEBB>
// <20> <> <EFBFBD> Ը<EFBFBD> <D4B8> <EFBFBD> <EFBFBD> <EFBFBD> Ҫ<EFBFBD> <D2AA> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
Vector3 cameraPos = target - transform . forward * distance ;
targetPos = target ;
this . distance = distance ;
offset = new Vector3 ( 0 , 0 , - distance ) ;
2025-02-17 15:14:40 +08:00
if ( moveTime ! = - 1 )
2025-02-14 17:09:41 +08:00
{
transform . DOMove ( cameraPos , moveTime ) ;
}
else
{
transform . position = cameraPos ;
}
2025-02-14 13:20:54 +08:00
}
2025-02-10 10:54:47 +08:00
public void OnMouseEnterObj ( GameObject obj )
{
TipItem tip = obj . GetComponent < TipItem > ( ) ;
if ( tip ! = null )
{
tip . OnEnter ( ) ;
}
}
public void OnMouseExitObj ( GameObject obj )
{
TipItem tip = obj . GetComponent < TipItem > ( ) ;
if ( tip ! = null )
{
tip . OnExit ( ) ;
}
}
2025-02-08 16:22:00 +08:00
// <20> ƶ<EFBFBD> Ŀ<EFBFBD> <C4BF> <EFBFBD> <EFBFBD>
private void MoveTarget ( )
{
float mouseX = Input . GetAxis ( "Mouse X" ) * moveSpeed ;
float mouseY = Input . GetAxis ( "Mouse Y" ) * moveSpeed ;
transform . Translate ( new Vector3 ( - mouseX , - mouseY , 0 ) ) ;
2025-02-17 15:14:40 +08:00
targetPos + = new Vector3 ( - mouseX , - mouseY , 0 ) ;
2025-02-08 16:22:00 +08:00
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
private void ZoomCamera ( float scroll )
{
distance - = scroll * 5f ; // <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ٶ<EFBFBD>
2025-02-10 10:54:47 +08:00
distance = Mathf . Clamp ( distance , distanceMin , distanceMax ) ; // <20> <> <EFBFBD> ƾ<EFBFBD> <C6BE> 뷶Χ
2025-02-08 16:22:00 +08:00
offset = new Vector3 ( 0 , 0 , - distance ) ;
UpdateCameraPosition ( ) ;
}
// <20> <> ת<EFBFBD> <D7AA> <EFBFBD> <EFBFBD>
private void RotateCamera ( )
{
// <20> <> ȡ<EFBFBD> <C8A1> <EFBFBD> <EFBFBD> <EFBFBD> ƶ<EFBFBD> <C6B6> <EFBFBD>
float mouseX = Input . GetAxis ( "Mouse X" ) * rotateSpeed ;
float mouseY = Input . GetAxis ( "Mouse Y" ) * rotateSpeed ;
2025-03-17 17:21:06 +08:00
switch ( type )
{
case RotationType . Orbit :
// <20> <> <EFBFBD> <EFBFBD> ƫ<EFBFBD> <C6AB> <EFBFBD> Ǻ<C7BA> <CDB8> <EFBFBD> <EFBFBD> <EFBFBD>
yaw + = mouseX ;
pitch - = mouseY ; // ע<> ⣺<EFBFBD> <E2A3BA> <EFBFBD> <EFBFBD> Y <20> <> <EFBFBD> ƶ<EFBFBD> <C6B6> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> 븩<EFBFBD> <EBB8A9> <EFBFBD> <EFBFBD> <EFBFBD> ෴
pitch = Mathf . Clamp ( pitch , pitchMinMax . x , pitchMinMax . y ) ; // <20> <> <EFBFBD> Ƹ<EFBFBD> <C6B8> <EFBFBD> <EFBFBD> Ƿ<EFBFBD> Χ
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> <CEBB>
UpdateCameraPosition ( ) ;
break ;
case RotationType . Spherical :
// <20> <> ȫ<EFBFBD> <C8AB> <EFBFBD> ɵ<EFBFBD> <C9B5> <EFBFBD> ת<EFBFBD> <D7AA> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> X/Y/Z<> <5A> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
target . Rotate ( Vector3 . up , mouseX , Space . World ) ; // ˮƽ <CBAE> <C6BD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Y<EFBFBD> <59> <EFBFBD> <EFBFBD> ת
target . Rotate ( Vector3 . right , - mouseY , Space . Self ) ; // <20> <> ֱ<EFBFBD> <D6B1> <EFBFBD> <EFBFBD> X<EFBFBD> <58> <EFBFBD> <EFBFBD> ת
break ;
}
2025-02-08 16:22:00 +08:00
2025-03-17 17:21:06 +08:00
}
2025-02-08 16:22:00 +08:00
2025-03-17 17:21:06 +08:00
public void ChangeMode ( RotationType type )
{
this . type = type ;
target . position = targetPosition ;
target . eulerAngles = targetRotate ;
ResetCamera ( this . target ) ;
2025-02-08 16:22:00 +08:00
}
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> úͳ<C3BA> <CDB3> <EFBFBD>
2025-02-14 13:20:54 +08:00
private void UpdateCameraPosition ( float moveTime = - 1 )
2025-02-08 16:22:00 +08:00
{
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ת<EFBFBD> <D7AA> <EFBFBD> <EFBFBD> ƫ<EFBFBD> <C6AB> <EFBFBD> <EFBFBD>
Quaternion rotation = Quaternion . Euler ( pitch , yaw , 0 ) ;
Vector3 rotatedOffset = rotation * offset ;
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> <CEBB>
2025-02-14 13:20:54 +08:00
if ( moveTime ! = - 1 )
{
transform . DOMove ( targetPos + rotatedOffset , moveTime ) . onUpdate = ( ) = >
// <20> <> <EFBFBD> <EFBFBD> ʼ <EFBFBD> ճ<EFBFBD> <D5B3> <EFBFBD> Ŀ<EFBFBD> <C4BF> <EFBFBD> <EFBFBD>
transform . LookAt ( targetPos ) ;
}
else
{
transform . position = targetPos + rotatedOffset ;
// <20> <> <EFBFBD> <EFBFBD> ʼ <EFBFBD> ճ<EFBFBD> <D5B3> <EFBFBD> Ŀ<EFBFBD> <C4BF> <EFBFBD> <EFBFBD>
transform . LookAt ( targetPos ) ;
}
2025-02-08 16:22:00 +08:00
}
}