C# 分形树的构造问题
我一直在尝试利用我在这方面所学到的东西来制作一些我可以用于我自己项目的东西。我想要一个脚本,可以生成统一的树。我觉得我已经取得了很大的进步,但是遇到了困难 我设置脚本的方式是,它根据两个参数缩放分支:C# 分形树的构造问题,c#,unity3d,C#,Unity3d,我一直在尝试利用我在这方面所学到的东西来制作一些我可以用于我自己项目的东西。我想要一个脚本,可以生成统一的树。我觉得我已经取得了很大的进步,但是遇到了困难 我设置脚本的方式是,它根据两个参数缩放分支: a) 公共“childScale”变量 b) 从上一个分支发芽的分支数 最大的问题是,当儿童成为非均匀比例对象的父对象时,他们会以非预期的方式扭曲。为了绕开它,我制作了其他游戏对象的预制实例(默认情况下是1,1,1)子对象。这些游戏对象也是包含其他预制实例的其他游戏对象的父对象。这是有问题的,
- a) 公共“childScale”变量李>
- b) 从上一个分支发芽的分支数
- 主要问题是:尽管缺乏连续的层次结构,但如何在允许树的整体形式不一致的情况下保持分形原则的缩放完整性
- 到目前为止,第二个问题是我的'thicknessScaler'变量使我的分支太细,尤其是分支越多。现在,它只是将1除以分支的数量,所以我需要一个没有剃掉那么多的分支
使用UnityEngine;
使用系统集合;
公共类三要素:单一行为
{
public GameObject[]分支;//最后一个分支是指向的,而所有其他分支都是四舍五入的
公共int最大深度;
公共交通量表;
公共浮点maxTwist;//暂时关闭
public Vector3 baseBranchSize;//实例化预置的比例
public int minBranchDensity;//每个节点的分支数量,随机
公共内部最大密度;
公共浮动分行;
私有整数深度;
私密性;
私有游戏对象分支;
私有游戏对象实例;
私人祖父母;
私人浮动置换;
专用浮动厚度缩放器=1;
私人股本密度;
私有void Start()
{
if(深度<最大深度)
分支=分支[0];
其他的
分支机构=分支机构[1];
实例=实例化(分支);
instance.transform.parent=transform;//预制(非均匀比例)由均匀缩放的游戏对象的子对象构成。
如果(深度==0)
{
位移=基本分支尺寸y;
instance.transform.localScale=baseBranchSize;
}
否则//乘以密度^深度可以弥补缩小的游戏对象,因为预制实例不会按比例传递
//而游戏对象是这样的。只有当树的所有“深度”都有相同数量的分支时,这才有效。
//因为游戏对象必须保持一致,所以y轴的所有缩放都必须发生在预设实例中。
{
位移=基本支管尺寸y*Mathf.Pow(密度、深度);
//如果(深度==2)3
打印(baseBranchSize.y*Mathf.Pow(父密度、深度));
instance.transform.localScale=新矢量3
(
baseBranchSize.x,
baseBranchSize.y*Mathf.Pow(父密度、深度),
baseBranchSize.z
);
}
instance.transform.localPosition=new Vector3(0f,1f*(displace/2),0f);//在游戏对象的一端预设实例枢轴,用于旋转。
instance.transform.localRotation=Quaternion.Euler(0f,0f,0f);
变换旋转(随机范围(-maxTwist*((浮点)(深度+1)/maxDepth),maxTwist*((浮点)(深度+1)/maxDepth)),0f,0f);
//增加潜在随机扭曲越多,分支越小。
if(深度<最大深度)
{
start例程(CreateChildren());
}
}
私有void更新()
{
}
私有IEnumerator CreateChildren()
{
branchDensity=Random.Range(最小branchDensity,最大branchDensity+1);
for(int i=0;iusing UnityEngine;
using System.Collections;
public class TreeFractal : MonoBehaviour
{
public GameObject[] branches; // the last branch is pointed, while all the others are rounded
public int maxDepth;
public float childScale;
public float maxTwist; // OFF temporarily
public Vector3 baseBranchSize; // proportions of instantiated prefab
public int minBranchDensity; // amount of offshoots per node, randomized
public int maxBranchDensity;
public float branchTilt;
private int depth;
private int branchDensity;
private GameObject branch;
private GameObject instance;
private TreeFractal grandparent;
private float displace;
private float thicknessScaler = 1;
private float parentDensity;
private void Start()
{
if (depth < maxDepth)
branch = branches[0];
else
branch = branches[1];
instance = Instantiate(branch);
instance.transform.parent = transform; // prefabs (non-uniform proportions) are made the children of uniform-scaled Game Objects.
if (depth == 0)
{
displace = baseBranchSize.y;
instance.transform.localScale = baseBranchSize;
}
else //Multiplication by density^depth is to make up for the shrinking game objects, as the prefab instances do not pass on their scale
//while the GameObjects do. This only works when all 'depths' of the tree have the same amount of offshoots.
//Because the GameObject must remain uniform, all scaling of the y axis must occur in the prefab instance.
{
displace = baseBranchSize.y * Mathf.Pow(parentDensity, depth);
//if (depth == 2)3
print(baseBranchSize.y * Mathf.Pow(parentDensity, depth));
instance.transform.localScale = new Vector3
(
baseBranchSize.x,
baseBranchSize.y * Mathf.Pow(parentDensity, depth),
baseBranchSize.z
);
}
instance.transform.localPosition = new Vector3(0f, 1f * (displace / 2), 0f); //prefab instance pivots at one end of the GameObject, for rotations.
instance.transform.localRotation = Quaternion.Euler(0f, 0f, 0f);
transform.Rotate(Random.Range(-maxTwist * ((float)(depth + 1)/ maxDepth), maxTwist * ((float)(depth + 1) / maxDepth)), 0f, 0f);
//increases the potential randomized twist more, the smaller the branches get.
if (depth < maxDepth)
{
StartCoroutine(CreateChildren());
}
}
private void Update()
{
}
private IEnumerator CreateChildren()
{
branchDensity = Random.Range(minBranchDensity, maxBranchDensity + 1);
for (int i = 0; i < branchDensity; i++)
{
yield return new WaitForSeconds(Random.Range(0.1f, 0.5f));
Quaternion quaternion = BranchRotater(branchDensity, i);
new GameObject("Fractal Child").AddComponent<TreeFractal>().
Initialize(this, i, quaternion);
}
}
private Quaternion BranchRotater (int density, int childIndex) //returns the rotation of the branch depending on the index and amount of branches.
{
Quaternion quaternion = Quaternion.Euler
(0f,
(360 / density) * childIndex,
branchTilt
);
return quaternion;
}
private void Initialize(TreeFractal parent, int childIndex, Quaternion quaternion)
{
branches = parent.branches;
branchTilt = parent.branchTilt;
maxDepth = parent.maxDepth;
depth = parent.depth + 1;
baseBranchSize = parent.baseBranchSize;
maxTwist = parent.maxTwist;
transform.parent = parent.transform;
childScale = parent.childScale;
minBranchDensity = parent.minBranchDensity;
maxBranchDensity = parent.maxBranchDensity;
thicknessScaler = 1f / parent.branchDensity; // I need a better equation here. This scaler is too small.
transform.localScale = Vector3.one * childScale * thicknessScaler; // reproportions all 3 axes of child GameObject so that
//the child remains of uniform scale. This must then be compensated for in the scaling of said object's child-prefab.
parentDensity = parent.branchDensity;
transform.localPosition = Vector3.up * parent.displace; //positions child relative to its parent
transform.localRotation = quaternion;
}
}
prefab:
[root]
|--->[non-uni]
| |---> mesh
.
.
[childRoot]