Показать сообщение отдельно
Старый 06.08.2013, 05:24   #1737
RegIon
Элита
 
Аватар для RegIon
 
Регистрация: 16.01.2010
Адрес: Новосибирск
Сообщений: 2,158
Написано 502 полезных сообщений
(для 1,012 пользователей)
Ответ: Вопросы от новичка

Сообщение от WISHMASTER35 Посмотреть сообщение
Lestar, вчера искал, но не нашел. Когда-то давно видел.
Andvrok, я пробовал кривыми настраивать силу выталкивания в зависимости от глубины погружения. Вообщем-то получалось тоже, что и без кривой.

Я думаю можно как-то создать амплитуду качания на воде. И увеличивать\уменьшать ее в зависимости от скорости. Но все это я слабо себе представляю и сделать не получается.

Кстати, лучше сделать затухание скорости? Если просто умножать на 0.95, то большая скорость уменьшается медленно, а маленькая скорость так и не доходит до нуля.
Плавающие тела, переменная WaterY - высота воды.

// Buoyancy.cs
// by Alex Zhdankin
// Version 2.1
//
// http://forum.unity3d.com/threads/72974-Buoyancy-script
//
// Terms of use: do whatever you like

using System.Collections.Generic;
using UnityEngine;

public class 
Buoyancy MonoBehaviour
{
//    public Ocean ocean;

    
public float waterY=0f;
    public 
float density 500;
    public 
int slicesPerAxis 2;
    public 
bool isConcave false;
    public 
int voxelsLimit 16;

    private const 
float DAMPFER 0.1f;
    private const 
float WATER_DENSITY 1000;

    private 
float voxelHalfHeight;
    private 
Vector3 localArchimedesForce;
    private List<
Vector3voxels;
    private 
bool isMeshCollider;
    private List<
Vector3[]> forces// For drawing force gizmos

    /// <summary>
    /// Provides initialization.
    /// </summary>
    
private void Start()
    {
        
forces = new List<Vector3[]>(); // For drawing force gizmos

        // Store original rotation and position
        
var originalRotation transform.rotation;
        var 
originalPosition transform.position;
        
transform.rotation Quaternion.identity;
        
transform.position Vector3.zero;

        
// The object must have a collider
        
if (collider == null)
        {
            
gameObject.AddComponent<MeshCollider>();
            
Debug.LogWarning(string.Format("[Buoyancy.cs] Object \"{0}\" had no collider. MeshCollider has been added."name));
        }
        
isMeshCollider GetComponent<MeshCollider>() != null;

        var 
bounds collider.bounds;
        if (
bounds.size.bounds.size.y)
        {
            
voxelHalfHeight bounds.size.x;
        }
        else
        {
            
voxelHalfHeight bounds.size.y;
        }
        if (
bounds.size.voxelHalfHeight)
        {
            
voxelHalfHeight bounds.size.z;
        }
        
voxelHalfHeight /= slicesPerAxis;

        
// The object must have a RidigBody
        
if (rigidbody == null)
        {
            
gameObject.AddComponent<Rigidbody>();
            
Debug.LogWarning(string.Format("[Buoyancy.cs] Object \"{0}\" had no Rigidbody. Rigidbody has been added."name));
        }
        
rigidbody.centerOfMass = new Vector3(0, -bounds.extents.0f0) + transform.InverseTransformPoint(bounds.center);

        
voxels SliceIntoVoxels(isMeshCollider && isConcave);

        
// Restore original rotation and position
        
transform.rotation originalRotation;
        
transform.position originalPosition;

        
float volume rigidbody.mass density;

        
WeldPoints(voxelsvoxelsLimit);

        
float archimedesForceMagnitude WATER_DENSITY Mathf.Abs(Physics.gravity.y) * volume;
        
localArchimedesForce = new Vector3(0archimedesForceMagnitude0) / voxels.Count;

        
Debug.Log(string.Format("[Buoyancy.cs] Name=\"{0}\" volume={1:0.0}, mass={2:0.0}, density={3:0.0}"namevolumerigidbody.massdensity));
    }

    
/// <summary>
    /// Slices the object into number of voxels represented by their center points.
    /// <param name="concave">Whether the object have a concave shape.</param>
    /// <returns>List of voxels represented by their center points.</returns>
    /// </summary>
    
private List<Vector3SliceIntoVoxels(bool concave)
    {
        var 
points = new List<Vector3>(slicesPerAxis slicesPerAxis slicesPerAxis);

        if (
concave)
        {
            var 
meshCol GetComponent<MeshCollider>();

            var 
convexValue meshCol.convex;
            
meshCol.convex false;

            
// Concave slicing
            
var bounds collider.bounds;
            for (
int ix 0ix slicesPerAxisix++)
            {
                for (
int iy 0iy slicesPerAxisiy++)
                {
                    for (
int iz 0iz slicesPerAxisiz++)
                    {
                        
float x bounds.min.bounds.size.slicesPerAxis * (0.5f ix);
                        
float y bounds.min.bounds.size.slicesPerAxis * (0.5f iy);
                        
float z bounds.min.bounds.size.slicesPerAxis * (0.5f iz);

                        var 
transform.InverseTransformPoint(new Vector3(xyz));

                        if (
PointIsInsideMeshCollider(meshColp))
                        {
                            
points.Add(p);
                        }
                    }
                }
            }
            if (
points.Count == 0)
            {
                
points.Add(bounds.center);
            }

            
meshCol.convex convexValue;
        }
        else
        {
            
// Convex slicing
            
var bounds GetComponent<Collider>().bounds;
            for (
int ix 0ix slicesPerAxisix++)
            {
                for (
int iy 0iy slicesPerAxisiy++)
                {
                    for (
int iz 0iz slicesPerAxisiz++)
                    {
                        
float x bounds.min.bounds.size.slicesPerAxis * (0.5f ix);
                        
float y bounds.min.bounds.size.slicesPerAxis * (0.5f iy);
                        
float z bounds.min.bounds.size.slicesPerAxis * (0.5f iz);

                        var 
transform.InverseTransformPoint(new Vector3(xyz));

                        
points.Add(p);
                    }
                }
            }
        }

        return 
points;
    }

    
/// <summary>
    /// Returns whether the point is inside the mesh collider.
    /// </summary>
    /// <param name="c">Mesh collider.</param>
    /// <param name="p">Point.</param>
    /// <returns>True - the point is inside the mesh collider. False - the point is outside of the mesh collider. </returns>
    
private static bool PointIsInsideMeshCollider(Collider cVector3 p)
    {
        
Vector3[] directions = { Vector3.upVector3.downVector3.leftVector3.rightVector3.forwardVector3.back };

        foreach (var 
ray in directions)
        {
            
RaycastHit hit;
            if (
c.Raycast(new Ray(ray 1000ray), out hit1000f) == false)
            {
                return 
false;
            }
        }

        return 
true;
    }

    
/// <summary>
    /// Returns two closest points in the list.
    /// </summary>
    /// <param name="list">List of points.</param>
    /// <param name="firstIndex">Index of the first point in the list. It's always less than the second index.</param>
    /// <param name="secondIndex">Index of the second point in the list. It's always greater than the first index.</param>
    
private static void FindClosestPoints(IList<Vector3> list, out int firstIndexout int secondIndex)
    {
        
float minDistance float.MaxValuemaxDistance float.MinValue;
        
firstIndex 0;
        
secondIndex 1;

        for (
int i 0< list.Count 1i++)
        {
            for (
int j 1< list.Countj++)
            {
                
float distance Vector3.Distance(list[i], list[j]);
                if (
distance minDistance)
                {
                    
minDistance distance;
                    
firstIndex i;
                    
secondIndex j;
                }
                if (
distance maxDistance)
                {
                    
maxDistance distance;
                }
            }
        }
    }

    
/// <summary>
    /// Welds closest points.
    /// </summary>
    /// <param name="list">List of points.</param>
    /// <param name="targetCount">Target number of points in the list.</param>
    
private static void WeldPoints(IList<Vector3> list, int targetCount)
    {
        if (list.
Count <= || targetCount 2)
        {
            return;
        }

        while (list.
Count targetCount)
        {
            
int firstsecond;
            
FindClosestPoints(list, out firstout second);

            var 
mixed = (list[first] + list[second]) * 0.5f;
            list.
RemoveAt(second); // the second index is always greater that the first => removing the second item first
            
list.RemoveAt(first);
            list.
Add(mixed);
        }
    }

    
/// <summary>
    /// Returns the water level at given location.
    /// </summary>
    /// <param name="x">x-coordinate</param>
    /// <param name="z">z-coordinate</param>
    /// <returns>Water level</returns>
    
private float GetWaterLevel(float xfloat z)
    {
//        return ocean == null ? 0.0f : ocean.GetWaterHeightAtLocation(x, z);
        
return waterY;
    }

    
/// <summary>
    /// Calculates physics.
    /// </summary>
    
private void FixedUpdate()
    {
        
forces.Clear(); // For drawing force gizmos

        
foreach (var point in voxels)
        {
            var 
wp transform.TransformPoint(point);
            
float waterLevel GetWaterLevel(wp.xwp.z);

            if (
wp.voxelHalfHeight waterLevel)
            {
                
float k = (waterLevel wp.y) / (voxelHalfHeight) + 0.5f;
                if (
1)
                {
                    
1f;
                }
                else if (
0)
                {
                    
0f;
                }

                var 
velocity rigidbody.GetPointVelocity(wp);
                var 
localDampingForce = -velocity DAMPFER rigidbody.mass;
                var 
force localDampingForce Mathf.Sqrt(k) * localArchimedesForce;
                
rigidbody.AddForceAtPosition(forcewp);

                
forces.Add(new[] { wpforce }); // For drawing force gizmos
            
}
        }
    }

    
/// <summary>
    /// Draws gizmos.
    /// </summary>
    
private void OnDrawGizmos()
    {
        if (
voxels == null || forces == null)
        {
            return;
        }

        const 
float gizmoSize 0.05f;
        
Gizmos.color Color.yellow;

        foreach (var 
p in voxels)
        {
            
Gizmos.DrawCube(transform.TransformPoint(p), new Vector3(gizmoSizegizmoSizegizmoSize));
        }

        
Gizmos.color Color.cyan;

        foreach (var 
force in forces)
        {
            
Gizmos.DrawCube(force[0], new Vector3(gizmoSizegizmoSizegizmoSize));
            
Gizmos.DrawLine(force[0], force[0] + force[1] / rigidbody.mass);
        }
    }


Юзай http://forum.unity3d.com/attachment....6&d=1294425510
Только перепиши немного, а то там уровень воды постоянно на 0,0,0 , не помню какая переменная.

Думаю силы к фИЗ телам прилагать умеешь .
Для колебаний - делай псевдослучайные толчки ввверх или вниз, ну или волны, на уровне меша и колайдера
__________________
Сайт: http://iexpo.ml
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
WISHMASTER35 (07.08.2013)