底:保证固定不让整体呗移动() ——(确定相对位置)
改变头部的位置。注意点:移动的位置在底部为中心的半径x的范围圈内
头部的就是一个不被可见的碰撞体,唯一的功能就是在范围内移动
using UnityEngine;
public class Joystick : MonoBehaviour
{
public Transform 头Obj_A;
public Transform stable_Y_Object;
void Update()
{
transform.LookAt(头Obj_A.transform, stable_Y_Object.transform.localPosition);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class JoystickHandleController : MonoBehaviour
{
public Transform anchorPoint;
public float initialRadius = 0.15f;
private float maxRadius;
private bool isDragging;
public float moveTime = 0.5f;
private Coroutine iEBackJoystick;
private void Start()
{
maxRadius = initialRadius;
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (hit.collider.gameObject == gameObject)
{
isDragging = true;
StopBack();
}
}
}
else if (Input.GetMouseButtonUp(0))
{
isDragging = false;
StartBack();
}
if (isDragging)
{
Plane plane = new Plane(transform.up, transform.position);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float distance;
if (plane.Raycast(ray, out distance))
{
Vector3 intersectionPoint = ray.GetPoint(distance);
Vector3 constrainedPosition = anchorPoint.InverseTransformPoint(intersectionPoint);
Vector3 offset = constrainedPosition - anchorPoint.localPosition;
offset.y = anchorPoint.localPosition.y;
if (offset.magnitude > maxRadius)
{
offset = offset.normalized * maxRadius;
offset.y = anchorPoint.localPosition.y;
}
transform.localPosition = offset;
}
}
}
private IEnumerator JoystickBack()
{
Vector3 startPosition = transform.localPosition;
float elapsedTime = 0f;
while (elapsedTime < moveTime)
{
transform.localPosition = Vector3.Lerp(startPosition, anchorPoint.localPosition, elapsedTime / moveTime);
yield return null;
elapsedTime += Time.deltaTime;
}
}
public void StartBack()
{
if (iEBackJoystick == null&& transform.localPosition!= anchorPoint.localPosition)
{ iEBackJoystick = StartCoroutine(JoystickBack()); }
}
public void StopBack()
{
if (iEBackJoystick != null) {
StopCoroutine(iEBackJoystick);
iEBackJoystick = null;
}
}
}
首先,通过Plane plane = new Plane(transform.up, transform.position)创建了一个新的平面。此平面的方向向量是 transform.up,这表明平面是垂直于Y轴的,通过物体的位置定义其位置。
然后,创建一个从鼠标的屏幕位置发出的射线 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition)。这是一个从主相机朝向鼠标光标的射线。
然后,它用刚刚创建的射线与平面进行相交,并用 out 关键字得到射线与平面的交点距离。这是通过 if (plane.Raycast(ray, out distance)) 实现的。如果射线与平面相交,该函数返回true,并计算出射线与平面的交点距离。
然后,通过 Vector3 intersectionPoint = ray.GetPoint(distance), 计算出射线和平面的交点。
紧接着,通过 Vector3 constrainedPosition = anchorPoint.InverseTransformPoint(intersectionPoint),将得到的交点限制在了手柄所在的平面内。
然后,通过 Vector3 offset = constrainedPosition - anchorPoint.localPosition,计算出交点与手柄初始位置间的向量偏移量,然后限制了这个偏移量的y分量等于初始位置的y分量( offset.y = anchorPoint.localPosition.y ),这主要是为了保证交点仍在手柄所在的平面内。
最后,通过transform.localPosition = offset,将手柄移动到偏移向量与初始位置之和的位置。 这样,可以观测到鼠标移动时,手柄同时在其所在平面内移动。