【Unity3D】《跳舞的线》游戏的方块单方向拉伸实现案例
通过网盘分享的文件:CubeMoveMusic.unitypackage
链接: https://pan.baidu.com/s/1Rq-HH4H9qzVNtpQ84WXyUA?pwd=a7xn 提取码: a7xn
运行游戏点击空格动态创建拉伸的方块,由Speed控制速度,新方向是随机上下左右生成。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeMoveGameCamera : MonoBehaviour
{
private Vector3 constDir;
public GeneMap geneMap;
void Start()
{
constDir = transform.position - geneMap.defaultPos;
}
// Update is called once per frame
void Update()
{
transform.position = constDir + geneMap.GetPos();
}
}
生成移动方块以及单方向拉伸方块脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GeneMap : MonoBehaviour
{
public enum Side
{
Top, Bottom, Left, Right
}
public GameObject cubePrefab;
private GameObject movingCubeGo;
private Transform movingCubeTrans;
private Side moveSide;
public Vector3 defaultPos;
public float speed = 1f;
private Matrix4x4 rotationMatrix4x4;
private void Start()
{
rotationMatrix4x4 = Matrix4x4.TRS(Vector3.zero, cubePrefab.transform.localRotation, Vector3.one);
}
Side MirrorSide(Side side)
{
if (side == Side.Top)
{
return Side.Bottom;
}
if (side == Side.Bottom)
{
return Side.Top;
}
if (side == Side.Left)
{
return Side.Right;
}
if (side == Side.Right)
{
return Side.Left;
}
Debug.LogError("?");
return Side.Top;
}
public bool IsMoving()
{
return movingCubeGo != null;
}
public Vector3 GetPos()
{
Vector3 pos = defaultPos;
if (IsMoving())
{
//利用上一个移动物体的方向,通过不同方向的移动物体局部大小得到偏移量,而0.5f是下一个新物体一半的偏移
Vector3 oldOffset = Vector3.zero;
switch (moveSide)
{
case Side.Top:
oldOffset = new Vector3(0, 0, movingCubeTrans.localScale.z - 0.5f);
break;
case Side.Bottom:
oldOffset = new Vector3(0, 0, -movingCubeTrans.localScale.z + 0.5f);
break;
case Side.Left:
oldOffset = new Vector3(-movingCubeTrans.localScale.x + 0.5f, 0, 0);
break;
case Side.Right:
//例如上一个物体是右方向,则使用局部大小x作为偏移量数值,并且需要-0.5f来让新物体的整体恰好在前一个延伸物体的内部。
oldOffset = new Vector3(movingCubeTrans.localScale.x - 0.5f, 0, 0);
break;
default:
break;
}
pos = movingCubeTrans.position + rotationMatrix4x4.MultiplyPoint(oldOffset);
}
return pos;
}
private void Update()
{
if (movingCubeGo != null)
{
if (moveSide == Side.Top || moveSide == Side.Bottom)
{
movingCubeTrans.localScale = new Vector3(1, 1, movingCubeTrans.localScale.z + speed * Time.deltaTime);
}
else
{
movingCubeTrans.localScale = new Vector3(movingCubeTrans.localScale.x + speed * Time.deltaTime, 1, 1);
}
}
if (Input.GetKeyDown(KeyCode.Space))
{
Vector3 pos = GetPos();
movingCubeGo = GameObject.Instantiate(cubePrefab);
movingCubeTrans = movingCubeGo.transform;
List<int> sideList = new List<int>();
for (int i = 0; i < 4; i++)
{
if (i != (int)moveSide && i != (int)MirrorSide(moveSide))
{
sideList.Add(i);
}
}
int randomIndex = Random.Range(0, sideList.Count);
moveSide = (Side)sideList[randomIndex];
//1、新物体在进行朝着新方向移动时,需要对子物体Cube调整局部位置(目的:锚点轴心偏移,实现单方向延伸)
//2、newOffset用于将新移动物体偏移到新移动方向的上一个物体边缘位置点
Vector3 newOffset = Vector3.zero;
Vector3 newLocalScale = Vector3.one;
Transform childTrans = movingCubeTrans.Find("Cube");
childTrans.GetComponent<MeshRenderer>().material.SetColor("_Color", new Color(Random.Range(0, 256) / 255f, Random.Range(0, 256) / 255f, Random.Range(0, 256) / 255f, 1));
switch (moveSide)
{
case Side.Top:
childTrans.localPosition = new Vector3(0, 0, 0.5f);
newOffset = new Vector3(0, 0, 0.5f);
newLocalScale = new Vector3(1, 1, 0);
break;
case Side.Bottom:
childTrans.localPosition = new Vector3(0, 0, -0.5f);
newOffset = new Vector3(0, 0, -0.5f);
newLocalScale = new Vector3(1, 1, 0);
break;
case Side.Left:
childTrans.localPosition = new Vector3(-0.5f, 0, 0);
newOffset = new Vector3(-0.5f, 0, 0);
newLocalScale = new Vector3(0, 1, 1);
break;
case Side.Right:
//例如右方向的Cube子物体需要偏移(0.5f,0,0)保证锚点是在物体左侧
childTrans.localPosition = new Vector3(0.5f, 0, 0);
//右方向的新物体起点要在上一个物体的右侧边缘点作为起点,故x轴+0.5f
newOffset = new Vector3(0.5f, 0, 0);
//右方向的新物体大小X轴要从0开始
newLocalScale = new Vector3(0, 1, 1);
break;
default:
break;
}
movingCubeTrans.position = pos + rotationMatrix4x4.MultiplyPoint(newOffset);
movingCubeTrans.localScale = newLocalScale;
}
}
}