简书链接:解决缩放完美插入到物体上方的方法探讨
文章字数: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);

输出结果

image.png

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

image.png

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

image.png

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

关于计算任何轴心的方式我陷入了沉思

image.png
上图的黑色 平面是用于输出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 有点问题了
x

xxx

 一个是缩放的立方体照样 精准插入头部,另外一个是图表,我加了box mesh 等于图表大小, 缩放了rect size ,显然算得有点偏差了,缩放值越大偏差越大 ,现在我计算得到大小大概是20 ,但是显然中心点算错了,图表偏离那么多xx

所以各位大佬 到底怎么解决这个问题。

最后我突然发现我有把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)