private void Awake() { myTransform = transform; int collidersLength = boxColliders.Length; if (boxColliders != null && collidersLength > 0) { collisionData = new CollisionArea[collidersLength]; for (int i = 0; i < collidersLength; i++) { CollisionArea ca = new CollisionArea(); BoxCollider bc = boxColliders[i]; if (bc == null) { Debug.LogError("One of the Box Colliders is null!"); boxColliders = new BoxCollider[0]; return; } Transform bcTransform = bc.transform; Vector3 localScale = bcTransform.localScale; Vector3 coll_pos = bc.transform.position; Vector3 coll_size = bc.size; coll_size.x *= localScale.x; coll_size.y *= localScale.y; coll_size.z *= localScale.z; coll_pos.x -= coll_size.x / 2.0f; coll_pos.y -= coll_size.y / 2.0f; coll_pos.z -= coll_size.z / 2.0f; ca.position = coll_pos; ca.size = coll_size; collisionData[i] = ca; } } if (instanced) { drawArgsBuffer = new ComputeBuffer(1, 5 * sizeof(uint), ComputeBufferType.IndirectArguments); drawArgsBuffer.SetData(new uint[5] { fishMesh.GetIndexCount(0), (uint)fishesCount, 0, 0, 0 }); props = new MaterialPropertyBlock(); props.SetFloat("_UniqueID", Random.value); } }
void InitializeFishes() { instancingBounds = new Bounds(myTransform.position, Vector3.one * 1000); int collidersLength = boxColliders.Length; if (boxColliders != null && collidersLength > 0) { collisionData = new CollisionArea[collidersLength]; for (int i = 0; i < collidersLength; i++) { CollisionArea ca = new CollisionArea(); BoxCollider bc = boxColliders[i]; if (bc == null) { Debug.LogError("One of the Box Colliders is null!"); boxColliders = new BoxCollider[0]; return; } Transform bcTransform = bc.transform; Vector3 localScale = bcTransform.localScale; Vector3 coll_pos = bc.transform.position; Vector3 coll_size = bc.size; coll_size.x *= localScale.x; coll_size.y *= localScale.y; coll_size.z *= localScale.z; coll_pos.x -= coll_size.x / 2.0f; coll_pos.y -= coll_size.y / 2.0f; coll_pos.z -= coll_size.z / 2.0f; ca.position = coll_pos; ca.size = coll_size; collisionData[i] = ca; } } if (instanced) { drawArgsBuffer = new ComputeBuffer(1, 5 * sizeof(uint), ComputeBufferType.IndirectArguments); drawArgsBuffer.SetData(new uint[5] { fishMesh.GetIndexCount(0), (uint)fishesCount, 0, 0, 0 }); } currentFishesCount = fishesCount; oldFishesCount = currentFishesCount; }
private void Awake() { myTransform = transform; instancingBounds = new Bounds(myTransform.position, Vector3.one * 1000); int collidersLength = boxColliders.Length; if (boxColliders != null && collidersLength > 0) { collisionData = new CollisionArea[collidersLength]; for (int i = 0; i < collidersLength; i++) { CollisionArea ca = new CollisionArea(); BoxCollider bc = boxColliders[i]; if (bc == null) { Debug.LogError("One of the Box Colliders is null!"); boxColliders = new BoxCollider[0]; return; } Transform bcTransform = bc.transform; Vector3 localScale = bcTransform.localScale; Vector3 coll_pos = bc.transform.position; Vector3 coll_size = bc.size; coll_size.x *= localScale.x; coll_size.y *= localScale.y; coll_size.z *= localScale.z; coll_pos.x -= coll_size.x / 2.0f; coll_pos.y -= coll_size.y / 2.0f; coll_pos.z -= coll_size.z / 2.0f; ca.position = coll_pos; ca.size = coll_size; collisionData[i] = ca; } } }
void Start() { if (followTarget) { groupAnchor = target.position; } else { GeneratePath(); groupAnchor = targetPositions[0]; } fishesData = new FishBehaviourCPU2[fishesCount]; if (!instanced) { fishesTransforms = new Transform[fishesCount]; } for (int i = 0; i < fishesCount; i++) { fishesData[i] = CreateBehaviour(); fishesData[i].speed_offset = Random.value * 10.0f; if (!instanced) { fishesTransforms[i] = Instantiate(prefab, fishesData[i].position, Quaternion.identity).transform; } } if (boxColliders.Length <= 0) { collisionData = new CollisionArea[1] { new CollisionArea() } } ; collisionDataLength = boxColliders.Length <= 0 ? 0 : collisionData.Length; if (instanced) { fishBuffer = new ComputeBuffer(fishesCount, sizeof(float) * 9); fishBuffer.SetData(fishesData); fishInstancedMaterial.SetBuffer("fishBuffer", fishBuffer); } } FishBehaviourCPU2 CreateBehaviour() { FishBehaviourCPU2 behaviour = new FishBehaviourCPU2(); Vector3 pos = groupAnchor + Random.insideUnitSphere * spawnRadius; Quaternion rot = Quaternion.Slerp(transform.rotation, Random.rotation, 0.3f); switch (movementAxis) { case MovementAxis.XY: pos.z = rot.z = 0.0f; break; case MovementAxis.XZ: pos.y = rot.y = 0.0f; break; } behaviour.position = pos; behaviour.velocity = rot.eulerAngles; behaviour.speed = Random.Range(minSpeed, maxSpeed); behaviour.rot_speed = Random.Range(minRotationSpeed, maxRotationSpeed); return(behaviour); } void Update() { UpdateGroupAnchor(); var time = Time.time; var deltaTime = Time.deltaTime; for (int i = 0; i < fishesCount; i++) { FishBehaviourCPU2 fish = fishesData[i]; Transform fish_transform = instanced ? null : fishesTransforms[i]; if (!instanced) { fish.position = fish_transform.position; } if (movementAxis == MovementAxis.XY) { fish.position.z = 0.0f; } else if (movementAxis == MovementAxis.XZ) { fish.position.y = 0.0f; } var current_pos = fish.position; var current_rot = instanced ? Quaternion.identity : fish_transform.rotation; var noise = Mathf.PerlinNoise(time, fish.speed_offset) * 2.0f - 1.0f; var fish_velocity = fish.speed * (1.0f + noise * speedVariation); var separation = Vector3.zero; var alignment = Vector3.zero; var cohesion = groupAnchor; //@Collisions! Vector3 next_position = fish.position + (fish.velocity * 3) * (fish_velocity * deltaTime); Vector3 avoidance = new Vector3(0, 0, 0); for (int c = 0; c < collisionDataLength; c++) { CollisionArea ca = collisionData[c]; Vector3 collider_pos = ca.position; Vector3 collider_size = ca.size; if ((next_position.x >= collider_pos.x && next_position.x <= collider_pos.x + collider_size.x) && (next_position.y >= collider_pos.y && next_position.y <= collider_pos.y + collider_size.y) && (next_position.z >= collider_pos.z && next_position.z <= collider_pos.z + collider_size.z)) { Vector3 coll_point = collider_pos; coll_point.x += collider_size.x / 2.0f; coll_point.y += collider_size.y / 2.0f; coll_point.z += collider_size.z / 2.0f; avoidance += next_position - coll_point; avoidance = (avoidance).normalized; avoidance *= force; } } var nearby_fishes_count = 1; if (!instanced) { var nearbyBoids = Physics.OverlapSphere(current_pos, neighbourDistance, searchLayer); foreach (var boid in nearbyBoids) { if (boid.gameObject == fish_transform.gameObject) { continue; } var t = boid.transform; separation += GetSeparationVector(current_pos, t.position); alignment += t.forward; cohesion += t.position; } nearby_fishes_count = nearbyBoids.Length; } else { for (int j = 0; j < fishesCount; j++) { if (j == i) { continue; } FishBehaviourCPU2 other_fish = fishesData[j]; if ((current_pos - other_fish.position).magnitude < neighbourDistance) { separation += GetSeparationVector(current_pos, other_fish.position); alignment += other_fish.velocity; cohesion += other_fish.position; nearby_fishes_count++; } } } var avg = 1.0f / nearby_fishes_count; alignment *= avg; cohesion *= avg; cohesion = (cohesion - current_pos).normalized; var velocity = separation + alignment + cohesion; velocity += avoidance; if (movementAxis == MovementAxis.XY) { velocity.z = 0.0f; } else if (movementAxis == MovementAxis.XZ) { velocity.y = 0.0f; } var ip = Mathf.Exp(-fish.rot_speed * deltaTime); if (!instanced) { fish.velocity = velocity.normalized; var rotation = Quaternion.FromToRotation(Vector3.forward, velocity.normalized); if (rotation != current_rot) { fish_transform.rotation = Quaternion.Lerp(rotation, current_rot, ip); } } else { fish.velocity = Vector3.Lerp((velocity.normalized), (fish.velocity.normalized), ip); } fish.position += (instanced ? fish.velocity : fish_transform.forward) * (fish_velocity * deltaTime); if (!instanced) { fish_transform.position = fish.position; } fishesData[i] = fish; } //fishBuffer.SetData(fishesData); }