一)物体在视角中并跟随视角移动的效果
例:对准左上角的葡萄UI,按下GrabGrip键,获取到葡萄Icon,葡萄Icon会跟随视角移动。
1.物体.position=手柄.position+Offset,并且一直Update
//这个脚本挂LeftController中,就是左手手柄
public class myLaser : MonoBehaviour
{
private GameObject icon; //要显示在玩家视角的Icon
public GameObject iconPerfab; //Icon预制体
public float offset; //Icon在视角前面的距离
public float iconScale; //Icon的Scale
void Start()
{
icon = Instantiate(IconPerfab);
icon.transfrom.localScale=new Vector3(iconScale,iconScale,iconScale);
}
void Update()
{
//Icon的位置
icon.transfrom.position=new Vector3(
transform.position.x,
transform.positon.y,
transform.position.z+Offset);
}
...
}
但运行后Icon.position.z会一直+offset,Icon一直移动,并不是静止不动的效果。
2.采用物理射线Ray
参考了SteamVR_LaserPointer的做法
//这个脚本挂LeftController中,就是左手手柄
public class myLaser : MonoBehaviour
{
private GameObject icon; //要显示在玩家视角的Icon
public GameObject iconPerfab; //Icon预制体
public float offset; //Icon在视角前面的距离
public float iconScale; //Icon的Scale
void Start()
{
Icon = Instantiate(IconPerfab);
}
void Update()
{
//物理射线raycast,射线从手柄发射
Ray raycast = new Ray(transform.position, transform.forward);
RaycastHit hit;
bool bHit = Physics.Raycast(raycast, out hit, 100, Mask);
//Icon会出现在射线的终点
Icon.transform.position=hit.point;
//当射线射到有碰撞盒的物体,并且物体的名字为Targect时,显示Icon
if(bHit&&hit.collider.gameObject.name=="Targect")
{
Icon.SetActive(true);
}
}
...
}
此时Icon会静止出现了,但前提是一定要射到有collider的物体才会显示,有局限性。
3.将Icon作为手柄的子物体
//这个脚本挂LeftController中,就是左手手柄
public class myLaser : MonoBehaviour
{
private GameObject icon; //要显示在玩家视角的Icon
public GameObject iconPerfab; //Icon预制体
public float offset; //Icon在视角前面的距离
public float iconScale; //Icon的Scale
void Start()
{
Icon = Instantiate(IconPerfab);
Icon.transform.position = new Vector3(
transform.position.x,
transform.position.y,
transform.position.z + offset);
Icon.transform.parent = transform;
Icon.transform.localScale = new Vector3(iconScale, iconScale, iconScale);
Icon.SetActive(false);
}
void Update()
{
//当射线射到有碰撞盒的物体,并且物体的名字为Targect时,显示Icon
//Icon一直朝向镜头
if(bHit&&hit.collider.gameObject.name=="Targect")
{
Icon.SetActive(true);
Icon.GetComponent<Transform>().LookAt(transform);
}
}
...
}
Icon作为手柄的子物体,将跟随手柄的移动而移动,从而达到图中的效果。
二)为一个物体添加多个材质球materials
例:葡萄Icon碰到草地会显示正常颜色,没有碰到则显示灰白色。
1.在Insepctor面板中添加material
2.脚本中调用
//这个脚本挂LeftController中,就是左手手柄
public class myLaser : MonoBehaviour
{
private Material[] materialGroup; //存放material的数值
public GameObject grapeIcon; //改变material的对象
void Start()
{
//注意,这里是materials,即是获取目标带有的全部material
materialGroup=grapeIcon.GetComponent<MeshRenderer>().materials;
}
void Update()
{
if (bHit && hit.collider.gameObject.name != "plane")
{
//从Insepctor得知,数组第二个元素是灰白色material
//注意,这里是material,没有带s
grapeIcon.GetComponent<MeshRenderer>().material = materialGroup[1];
}
if(bHit && hit.collider.gameObject.name == "plane")
{
//若碰到地面则是正常颜色
grapeIcon.GetComponent<MeshRenderer>().material = materialGroup[1];
}
}
...
}
三)单例的使用
例:有一个类MyPlane,它是一个植物生长的脚本,grow()函数控制植物生长;另一个类DayTime,它记录游戏内共度过了多少天的天数,dayTime变量记录天数;当dayTime++后,调用grow()函数。使用接口调用会遇到一下问题:①植物是到游戏后期才能创建的,也就是说不能在DayTime类中new一个MyPlane对象(public GameObject myPlane=MyPlane的GameObject)。②A植物在12点创建,B植物在6点创建,AB植物创建的时间不同,计算的时间也不同,使用GameObejct.getComponent().grow()会导致多且重复的判断语句,而且一旦植物数量多了,也不方便处理。