コード例 #1
0
        /// <summary>
        /// Implements building stuff
        /// </summary>
        /// <param name="camPos">The camera position OR the character position in a 3rd person controller</param>">
        protected virtual void DoBuild(Vector3 camPos, Vector3 forward, Vector3 hintedPlacePos)
        {
            if (player.selectedItemIndex < 0 || player.selectedItemIndex >= player.items.Count)
            {
                return;
            }

            InventoryItem  inventoryItem = player.GetSelectedItem();
            ItemDefinition currentItem   = inventoryItem.item;

            switch (currentItem.category)
            {
            case ItemCategory.Voxel:

                // Basic placement rules
                bool            canPlace          = crosshairOnBlock;
                Voxel           existingVoxel     = crosshairHitInfo.voxel;
                VoxelDefinition existingVoxelType = existingVoxel.type;
                Vector3         placePos;
                if (currentItem.voxelType.renderType == RenderType.Water && !canPlace)
                {
                    canPlace = true;                     // water can be poured anywhere
                    placePos = camPos + forward * 3f;
                }
                else
                {
                    placePos = crosshairHitInfo.voxelCenter + crosshairHitInfo.normal;
                    if (canPlace && crosshairHitInfo.normal.y == 1)
                    {
                        // Make sure there's a valid voxel under position (ie. do not build a voxel on top of grass)
                        canPlace = (existingVoxelType != null && existingVoxelType.renderType != RenderType.CutoutCross && (existingVoxelType.renderType != RenderType.Water || currentItem.voxelType.renderType == RenderType.Water));
                    }
                }
                VoxelDefinition placeVoxelType = currentItem.voxelType;

                // Check voxel promotion
                bool isPromoting = false;
                if (canPlace)
                {
                    if (existingVoxelType == currentItem.voxelType)
                    {
                        if (existingVoxelType.promotesTo != null)
                        {
                            // Promote existing voxel
                            //env.VoxelDestroy (crosshairHitInfo.voxelCenter);
                            placePos       = crosshairHitInfo.voxelCenter;
                            placeVoxelType = existingVoxelType.promotesTo;
                            isPromoting    = true;
                        }
                        else if (crosshairHitInfo.normal.y > 0 && existingVoxelType.biomeDirtCounterpart != null)
                        {
                            env.VoxelPlace(crosshairHitInfo.voxelCenter, existingVoxelType.biomeDirtCounterpart);
                        }
                    }
                }

                // Compute rotation
                int textureRotation = 0;
                if (placeVoxelType.placeFacingPlayer && placeVoxelType.renderType.supportsTextureRotation())
                {
                    // Orient voxel to player
                    if (Mathf.Abs(forward.x) > Mathf.Abs(forward.z))
                    {
                        if (forward.x > 0)
                        {
                            textureRotation = 1;
                        }
                        else
                        {
                            textureRotation = 3;
                        }
                    }
                    else if (forward.z < 0)
                    {
                        textureRotation = 2;
                    }
                }

                // Final check, does it overlap existing geometry?
                if (canPlace && !isPromoting)
                {
                    Quaternion rotationQ = Quaternion.Euler(0, Voxel.GetTextureRotationDegrees(textureRotation), 0);
                    canPlace = !env.VoxelOverlaps(placePos, placeVoxelType, rotationQ, 1 << env.layerVoxels);
                    if (!canPlace)
                    {
                        PlayCancelSound();
                    }
                }
                                #if UNITY_EDITOR
                else if (env.constructorMode)
                {
                    placePos       = hintedPlacePos;
                    placeVoxelType = currentItem.voxelType;
                    canPlace       = true;
                }
                                #endif
                // Finally place the voxel
                if (canPlace)
                {
                    // Consume item first
                    if (!env.buildMode)
                    {
                        player.ConsumeItem();
                    }
                    // Place it
                    float amount = inventoryItem.quantity < 1f ? inventoryItem.quantity : 1f;
                    env.VoxelPlace(placePos, placeVoxelType, true, placeVoxelType.tintColor, amount, textureRotation);

                    // Moves back character controller if voxel is put just on its position
                    const float minDist = 0.5f;
                    float       distSqr = Vector3.SqrMagnitude(camPos - placePos);
                    if (distSqr < minDist * minDist)
                    {
                        MoveTo(transform.position + crosshairHitInfo.normal);
                    }
                }
                break;

            case ItemCategory.Torch:
                if (crosshairOnBlock)
                {
                    GameObject torchAttached = env.TorchAttach(crosshairHitInfo, currentItem);
                    if (!env.buildMode && torchAttached != null)
                    {
                        player.ConsumeItem();
                    }
                }
                break;

            case ItemCategory.Model:
                if (!modelBuildInProgress)
                {
                    if (modelBuildPreview)
                    {
                        ModelPreviewCancel();
                        // check if building position is in frustum, otherwise cancel building
                        Vector3 viewportPos = env.cameraMain.WorldToViewportPoint(modelBuildPreviewPosition);
                        if (viewportPos.x < 0 || viewportPos.x > 1f || viewportPos.y < 0 || viewportPos.y > 1f || viewportPos.z < 0)
                        {
                            return;
                        }
                        modelBuildInProgress = true;
                        env.ModelPlace(modelBuildPreviewPosition, currentItem.model, currentItem.model.buildDuration, modelBuildRotation, 1f, true, FinishBuilding);
                        player.ConsumeItem();
                    }
                    else
                    {
                        modelBuildPreview = true;
                        modelBuildItem    = currentItem.model;
                        ModelBuildPreviewUpdate();
                    }
                }
                break;

            case ItemCategory.General:
                ThrowCurrentItem(camPos, forward);
                break;
            }
        }