简书链接:解决缩放完美插入到物体上方的方法探讨
文章字数:1064,阅读全文大约需要4分钟
首先被点击的物品 :
被点击的物品 有的是轴心 有的是 顶部 有的是底部。
如果是底部那么得到的物体y就是底部的需要把被点击物体y+当前物体材质的高度y加上才定位到顶点y,
然后要插入顶点 则直接y等于顶点就行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| /// <summary> /// 插入一个指定长度的柱子 位于指定的y轴上方 /// </summary> /// <param name="position"></param> /// <param name="floatY"></param> /// <param name="verticalMode">0 代表 底部 1 代表中心 1 代表 顶部</param> /// <param name="color"></param> internal static void DebugPrimitiveColorHeightInsertBar(Vector3 position, Vector3 size, float verticalMode, float selfHeight, Color color) { GameObject gameObject = GameObject.CreatePrimitive(PrimitiveType.Cube); gameObject.transform.localScale = new Vector3(0.1f, selfHeight, 0.1f); gameObject.GetComponent<Renderer>().material.color = color; float baseY; if (verticalMode == 0)//轴心为底部 加上自身大小 { baseY = position.y + size.y; } else if (verticalMode == 1)//轴心为中心 加上自身大小的一半 { baseY = position.y + (size.y / 2f);//轴心Y gameObject.transform.position = new Vector3(position.x, baseY +(selfHeight == 1 ? 0 : (selfHeight - 1) / 2f), position.z); } else { baseY = position.y;//轴心为顶部 则不需要加上自身大小 gameObject.transform.position = new Vector3(position.x, baseY + (selfHeight == 1 ? 0 : (selfHeight - 1) / 2f), position.z); } }
|
测试
1 2 3
| DebugPrimitiveColorHeightInsertBar(clickedMaterialGameObject.transform.position, clickedMaterialSize, 1, 3, Color.red); DebugPrimitiveColorHeightInsertBar(clickedMaterialGameObject.transform.position, clickedMaterialSize, 0, 30, Color.green);
|
输出结果

为了验证是否精确,于是我设置了一个超长缩放的条块

上面的红色平面 是和红色块是一起的,绿色平面在天上了

立方体的轴心是在立方体中心
但是测试的时候发现 还是基于y坐标加材质的高度才能计算出顶点,
但是测试其他不规则物体的时候轴心是底部,但是也是用了被点击物体y坐标+被点击物体的高度材质 + (1-(缩放后的高度)/2)
关于计算任何轴心的方式我陷入了沉思

上图的黑色 平面是用于输出y坐标轴心 忽略原始轴心的,但是网上这个方法似乎并不好使。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| Vector3 vector3 = CalcModelCenter(clickedMaterialGameObject.transform); DebugPrimitiveColorHeight(clickedMaterialGameObject.transform.position, vector3.y, Color.black);
internal static void DebugPrimitiveColorHeight(Vector3 position, float floatY, Color color) { GameObject gameObject = GameObject.CreatePrimitive(PrimitiveType.Plane); gameObject.transform.localScale = new Vector3(0.4f, 1, 0.4f); gameObject.GetComponent<Renderer>().material.color = color; gameObject.transform.position = new Vector3(position.x, floatY, position.z); }
/// <summary> /// 计算模型的中心点 /// </summary> /// <param name="tran"></param> /// <returns></returns> public static Vector3 CalcModelCenter(Transform tran) { Vector3 position = tran.position; Quaternion quaternion = tran.rotation; Vector3 scale = tran.localScale; tran.position = Vector3.zero; tran.rotation = Quaternion.Euler(Vector3.zero); tran.localScale = Vector3.one; Vector3 center = Vector3.zero; Renderer[] renders = tran.GetComponentsInChildren<Renderer>(); foreach (Renderer child in renders) { center += child.bounds.center; } center /= tran.GetComponentsInChildren<Renderer>().Length; Bounds bounds = new Bounds(center, Vector3.zero); foreach (Renderer item in renders) { bounds.Encapsulate(item.bounds); } tran.position = position; tran.rotation = quaternion; tran.localScale = scale; foreach (Transform item in tran) { item.position = item.position - bounds.center; } return bounds.center + tran.position; }
|
所以到底有没有忽略轴心真正得出顶点低点的正确代码呢。关于插入顶点的问题
在rect cavans world 有点问题了


一个是缩放的立方体照样 精准插入头部,另外一个是图表,我加了box mesh 等于图表大小, 缩放了rect size ,显然算得有点偏差了,缩放值越大偏差越大 ,现在我计算得到大小大概是20 ,但是显然中心点算错了,图表偏离那么多
所以各位大佬 到底怎么解决这个问题。
最后我突然发现我有把canvas也缩放过得呢,所以 获取父canvas 获取缩放值,也乘上缩放值 ,进行还原 真实的大小,得到了真实的大小/2就能得到摆放的位置了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| DebugSmartPrimitiveColorHeight(clickedMaterialGameObject.transform, clickedMaterialSize,0,Color.blue); float parentScale=chartGameObject.GetComponentInParent<Canvas>().transform.localScale.y; GameUtil.DebugSmallInsertArticleTopBy(clickedMaterialGameObject.transform, clickedMaterialSize, chartGameObject.GetComponentInChildren<Collider>().bounds.size.y* chartGameObject.transform.localScale.y* parentScale, 0,chartGameObject.transform); GameObject gameObjectTest = GameObject.CreatePrimitive(PrimitiveType.Cube); gameObjectTest.transform.localScale = new Vector3(0.2f, 30f, 0.2f); GameUtil.DebugSmallInsertArticleTopBy(clickedMaterialGameObject.transform, clickedMaterialSize, gameObjectTest.transform.localScale.y, 0, gameObjectTest.transform);
internal static void DebugSmallInsertArticleTopBy(Transform transform, Vector3 size, float selfHeight,float margin, Transform transformInnsert) {
float baseY; Vector3 vector3 = GetCenter(transform); baseY = vector3.y + size.y+ margin; transformInnsert.position = new Vector3(transform.position.x, baseY + (selfHeight == 1 ? 0 : (selfHeight - 1) / 2f), transform.position.z); Debug.Log("插入" + transform.name + "物体上方,被插入物体:" + transformInnsert.name + ",被插入物体高度:" + selfHeight + ",顶点y:" + baseY + ",插入的物体y:" + transformInnsert.position.y);
}
/// <summary> /// 获得中心点 /// </summary> /// <param name="target"></param> /// <returns></returns> public static Vector3 GetCenter(Transform target) { Renderer[] mrs = target.GetComponentsInChildren<Renderer>(); Vector3 center = target.transform.position; if (mrs.Length != 0) { Bounds bounds = new Bounds(center, Vector3.zero); foreach (Renderer item in mrs) { bounds.Encapsulate(item.bounds); } center = bounds.center; } return center; }
|
至于这个获取被点击物品中心点的应该还是有问题的,我发现得到的可能是底部位置 ,所以我加了被点击物体的高度才得到 顶部位置
最后总结思路:被点击物体的顶点
然后被点击物体的顶部位置 +(被插入的真实大小(需要还原缩放之前的大小)/2)