/// <summary> /// 生成路径的递归函数 /// </summary> /// <param name="lightningSegment">需要划分的线段</param> /// <param name="fractalTime">当前递归次数</param> /// <param name="maxFractalTime">最大递归次数</param> /// <param name="baseAttenuation">基础衰减</param> /// <param name="offsetRange">偏离值的范围</param> /// <param name="direction">闪电方向</param> /// <param name="forward">与闪电方向垂直的一个单位向量</param> /// <param name="right">与闪电方向垂直的一个单位向量</param> /// <param name="branchChance">生成分支的几率</param> private void GetFractcalLightning(LightningSegment lightningSegment, int fractalTime, int maxFractalTime, float baseAttenuation, Vector2 offsetRange, Vector3 direction, Vector3 forward, Vector3 right, float branchChance = 0f) { if (!lightningSegment.isLeaf() || fractalTime > maxFractalTime) { return; } float zOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); float xOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); Vector3 mid = lightningSegment.Middle() + xOffset * right + zOffset * forward; lightningSegment.LeftChild = new LightningSegment(lightningSegment.start, mid); lightningSegment.LeftChild.fractal = fractalTime + 1; lightningSegment.LeftChild.uv = lightningSegment.uv - LightningCreator.arrayForUV[lightningSegment.LeftChild.fractal]; lightningSegment.RightChild = new LightningSegment(mid, lightningSegment.end); lightningSegment.RightChild.fractal = fractalTime + 1; lightningSegment.RightChild.uv = lightningSegment.uv + LightningCreator.arrayForUV[lightningSegment.RightChild.fractal]; GetFractcalLightning(lightningSegment.LeftChild, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance); GetFractcalLightning(lightningSegment.RightChild, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance); if (Random.Range(0f, 1f) < branchChance) { //制作h形片段 zOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); xOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); float yOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y); Vector3 branchEnd = lightningSegment.Middle() + xOffset * right + zOffset * forward + yOffset * direction; lightningSegment.Branch = new LightningSegment(mid, branchEnd); lightningSegment.Branch.fractal = fractalTime + 1; lightningSegment.Branch.uv = lightningSegment.uv + LightningCreator.arrayForUV[lightningSegment.Branch.fractal]; GetFractcalLightning(lightningSegment.Branch, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance); } }
public LightningSegment(Vector3 s, Vector3 e) { start = s; end = e; LeftChild = null; RightChild = null; Branch = null; uv = 0.5f; fractal = 1; }
public void CreateLightning(Vector3 start, Vector3 end) { if (start == end) { return; } float Length = (end - start).magnitude; trunk = new LightningSegment(start, end); Vector2 OffsetRange = Length * new Vector2(MinOffset, MaxOffset); //计算一个正交基 Vector3 LightningDir = end - start; //找到不为0的一个分量 Vector3 forward; if (LightningDir.x != 0) { forward = new Vector3(-(LightningDir.y + LightningDir.z) / LightningDir.x, 1, 1); } else if (LightningDir.y != 0) { forward = new Vector3(1, -(LightningDir.x + LightningDir.z) / LightningDir.y, 1); } else if (LightningDir.z != 0) { forward = new Vector3(1, 1, -(LightningDir.x + LightningDir.y) / LightningDir.z); } else { return; } forward.Normalize(); Vector3 right = Vector3.Cross(LightningDir, forward); right.Normalize(); LightningDir.Normalize(); GetFractcalLightning(trunk, 1, FractalTime, BaseAttenuation, OffsetRange, LightningDir, forward, right, BranchChance); Mesh mesh = MakeMesh(trunk, Radius, RadiusAttenuation, Observer.position, Length); //创造新的闪电 GameObject go = Instantiate(templet) as GameObject; go.GetComponent <MeshFilter>().mesh = mesh; go.transform.position = Vector3.zero; go.transform.parent = transform; go.SetActive(true); }
private Mesh MakeMesh(LightningSegment lightningSegment, float radius, float attenuation, Vector3 obPos, float length) { Mesh mesh = new Mesh(); List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); List <Vector2> uvs = new List <Vector2>(); int idx = 0; SegmentToMesh(lightningSegment, vertices, triangles, uvs, obPos, radius, attenuation, ref idx); mesh.SetVertices(vertices); mesh.triangles = triangles.ToArray(); mesh.SetUVs(0, uvs); mesh.RecalculateNormals(); mesh.RecalculateBounds(); mesh.RecalculateTangents(); return(mesh); }
/// <summary> /// 填充Mesh的递归函数 /// </summary> /// <param name="lightningSegment">需要生成Mesh的线段</param> /// <param name="vertices"></param> /// <param name="triangle"></param> /// <param name="uv"></param> /// <param name="obPos">摄像机位置</param> /// <param name="radius">当前的闪电粗细</param> /// <param name="attenuation">分支闪电的衰减程度</param> /// <param name="idx">顶点序号</param> private void SegmentToMesh(LightningSegment lightningSegment, List <Vector3> vertices, List <int> triangle, List <Vector2> uv, Vector3 obPos, float radius, float attenuation, ref int idx) { if (lightningSegment.isLeaf()) { Vector3 zMid = lightningSegment.Middle(); Vector3 zNormal = Vector3.Cross(zMid - obPos, lightningSegment.end - lightningSegment.start).normalized; var finalR = radius * attenuation; if (lightningSegment.Branch == null) { //Z型片段的Mesh生成 vertices.Add(lightningSegment.start + finalR * zNormal); vertices.Add(lightningSegment.start - finalR * zNormal); vertices.Add(lightningSegment.end + finalR * zNormal); vertices.Add(lightningSegment.end - finalR * zNormal); triangle.Add(idx + 1); triangle.Add(idx); triangle.Add(idx + 2); triangle.Add(idx + 1); triangle.Add(idx + 2); triangle.Add(idx + 3); uv.Add(new Vector2(1, lightningSegment.uv)); uv.Add(new Vector2(0, lightningSegment.uv)); uv.Add(new Vector2(1, lightningSegment.uv)); uv.Add(new Vector2(0, lightningSegment.uv)); idx += 4; } } else { SegmentToMesh(lightningSegment.LeftChild, vertices, triangle, uv, obPos, radius, attenuation, ref idx); SegmentToMesh(lightningSegment.RightChild, vertices, triangle, uv, obPos, radius, attenuation, ref idx); if (lightningSegment.Branch != null) { SegmentToMesh(lightningSegment.Branch, vertices, triangle, uv, obPos, radius * attenuation, attenuation, ref idx); } } }
// Update is called once per frame void Update() { bool forward, back, left, right; forward = Input.GetKey(KeyCode.W); back = Input.GetKey(KeyCode.S); left = Input.GetKey(KeyCode.A); right = Input.GetKey(KeyCode.D); Vector3 camRight = Vector3.Cross(new Vector3(0, 1, 0), curentCamera.transform.forward).normalized; Vector3 camForward = -Vector3.Cross(new Vector3(0, 1, 0), camRight).normalized; Vector2 localClick = new Vector2(); Camera cam = GameDirector.Director.currentCamera.GetComponent <Camera>(); if (RectTransformUtility.RectangleContainsScreenPoint(Q, Input.mousePosition) && Input.GetMouseButtonDown(0)) { Debug.Log("Q skill"); foreach (GameObject enemy in GameDirector.Director.enemiesSpawned) { enemy.GetComponent <SlimeMovement>().stun(this.gameObject); LightningSegment.spawnLightningChain(this.gameObject, enemy, lightningLine); //Debug.Break(); } } else if (RectTransformUtility.RectangleContainsScreenPoint(W, Input.mousePosition) && Input.GetMouseButtonDown(0)) { Debug.Log("W skill"); } else if (RectTransformUtility.RectangleContainsScreenPoint(E, Input.mousePosition) && Input.GetMouseButtonDown(0)) { Debug.Log("E skill"); } else if (RectTransformUtility.RectangleContainsScreenPoint(R, Input.mousePosition) && Input.GetMouseButtonDown(0)) { Debug.Log("R skill"); Instantiate(spookPrefab, this.transform); GameDirector.Director.mainLight.GetComponent <Light>().intensity = 0; Invoke("lightBackOn", 10); } else { RaycastHit retVal = new RaycastHit(); Physics.Raycast(curentCamera.GetComponent <Camera>().ScreenPointToRay(Input.mousePosition), out retVal); Vector3 wantDir = new Vector3(); SlimeMovement attackTarget = null; if (retVal.collider != null) { SlimeMovement enemyHit = retVal.transform.gameObject.GetComponent <SlimeMovement>(); if (enemyHit != null) { wantDir = enemyHit.transform.position - this.transform.position; if ((enemyHit.transform.position - this.transform.position).magnitude < attackRange && Input.GetMouseButtonDown(0)) { attackTarget = enemyHit; } } else { wantDir = retVal.point + new Vector3(0, this.transform.position.y, 0) - this.transform.position; } wantDir = wantDir.normalized * moveSpeed; /*if (wantDir.magnitude > moveSpeed) * { * wantDir = wantDir.normalized * moveSpeed; * } * else if (wantDir.magnitude < moveSpeed / 2) * { * wantDir = wantDir.normalized * moveSpeed/2; * }*/ Debug.DrawRay(this.transform.position, wantDir, Color.cyan); if (Time.time - moveTime > 0 && Input.GetMouseButtonDown(0)) { float jump = Random.value > .7 ? moveSpeed : 0; phys.velocity = new Vector3(wantDir.x, phys.velocity.y + jump, wantDir.z); moveTime = Time.time + moveDownTime; //Debug.Log("moved!"); } } if (attackTarget && Time.time - nextAttackTime > 0) { energy += attack(attackTarget); nextAttackTime = Time.time + attackCoolDown; } } /*Vector3 newMove = new Vector3(); * newMove.y = phys.velocity.y; * if (forward) newMove += moveSpeed*camForward; * if (back) newMove += -moveSpeed * camForward; * if (left) newMove += -moveSpeed * camRight; * if (right) newMove += moveSpeed * camRight; */ //Debug.DrawRay(this.transform.position, camRight, Color.green); //Debug.DrawRay(this.transform.position, camForward, Color.red); //phys.velocity = newMove; }
private float attack(SlimeMovement enemy) { LightningSegment.spawnLightningChain(this.gameObject, enemy.gameObject, lightningLine); enemy.damage(1); return(1); }