|
|
Parent Movement |
Posted by: BusraSevim - 28-02-2024, 10:07 AM - Forum: Obi Softbody
- Replies (5)
|
|
Hello,
In my scene, there is a normal rotating cylinder and softbody spheres arranged around this cylinder. In order to attract the center of the cylinder, I apply a force to all spheres as follows:
Code: var forceDirection = (spin.transform.position - transform.position).normalized;
softBall.AddForce(forceDirection * force, ForceMode.Acceleration);
But at the same time, the cylinder is the parent object of these spheres. And when I rotate the cylinder, I want these spheres to rotate with the cylinder, like normal spheres. But they don't rotate, I can only see the strain vibration. They can rotate when I turn off the softbody features, but I shouldn't turn them off.
The rotation code of the cylinder is as follows:
Code: transform.Rotate(Vector3.forward,-_inputVector.x*spinRotateSpeed);
I use the solver and sphere softbody features in the sample scene named BallPool.
Thanks.
|
|
|
ObiCloth local space documentation is outdated? |
Posted by: CptnFabulous - 28-02-2024, 07:54 AM - Forum: Obi Cloth
- Replies (3)
|
|
Hi!
I have an object with an ObiSolver attached, with several ObiCloth shapes as children. The parent object needs to be moved and teleported, but this causes the rendered cloth to behave like it’s simply moving at high speeds, causing it to glitch out and behave in unnatural ways. To solve this, I’m trying to make the cloth simulation happen in the solver’s local space instead of world space, so that the parent’s movements don’t affect the cloth simulation. Not 100% realistic, but good enough for my purposes.
I've looked in the forum but haven't found a clear answer. In some posts I’ve seen people say that the simulations always occur in the local space of the solver itself, but that should mean the cloth is already operating in local space, which isn’t happening. I also found values for determining how much the local space values are affected by world space movement, but those are both set to zero.
I’m trying to make the cloth render in the solver’s local space instead of world space, and am looking at this documentation to try and figure it out: https://obi.virtualmethodstudio.com/manu...space.html
I’m currently using ObiCloth version 6.5.4, in the Unity Editor 2021.3.3f1, but the only detailed version of the documentation is for an older version. The later versions are marked red as incomplete and can’t be selected.
The documentation shows that in ObiSolver there’s a bool to enable local space simulation, but when I look at the script (both in the Inspector and at the code itself), no option exists. The two options I mentioned for determining world space influence both have comments that reference a ‘simulateInLocalSpace’ option, but returns no results when I use FindAll across the entire solution (aside from those two comments). I’ve got two images here to show how different the ObiSolver is in the inspector.
The image shown in the documentation:
The way it appears in my project:
So in the version I’m using, what do I need to do to ensure the cloth simulates in local space? I presume the feature must have been refactored and moved to a different section of the code, as I refuse to believe such an important feature would be outright removed.
Thanks!
|
|
|
Attaching a rope and updating position multiple times |
Posted by: stateofplay - 27-02-2024, 03:02 PM - Forum: Obi Rope
- Replies (4)
|
|
Hello,
I've been trying for the last couple of days to get the rope to do what we need and just can't quite get it to play nicely. Hoping you can help.
The use case is as follows:
- The rope is attached to the ground at one end
- Initially, the other end is attached to the player
- At specific places, when the player initiates it, we want the rope to attach to a point on the wall
- At this point, the rope would have three attachments (the ground, the point on the wall, and the player)
- This will then happen repeatedly so the rope may eventually have six attachments for example (ground, wall, wall, wall, wall, player)
My first approach was to create a single rope and use a pre-built blueprint and then just update the blueprint as time went on, adding new particle attachments and using the cursor to extend the length of the rope, but I couldn't get it to work.
Second, I tried generating a blueprint with code in case that was the issue, no luck.
My current approach was to generate a new rope for each segment (so each rope would just have two attachments and there would be a series of ropes in a list).
When I try to do this, the first rope attaches as desired properly. The second rope, attaches, but the positions of the particles do no update. So I can see the particles are attached but they are not in the right place.
Here is the code I am using to control the rope:
Code: public class RopeController : MonoBehaviour
{
private ObiSolver _solver;
private ObiRope _rope;
private ObiRopeBlueprint _blueprint;
private int _ropeId = -1;
private string _cp1Name;
private string _cp2Name;
public void Init(int ropeId, float ropeLength, float ropeMass,
float ropeRotationalMass, Transform attachment1, Transform attachment2)
{
StartCoroutine(InitCoro(ropeId, ropeLength, ropeMass, ropeRotationalMass, attachment1, attachment2));
}
private IEnumerator InitCoro(int ropeId, float ropeLength, float ropeMass,
float ropeRotationalMass, Transform attachment1, Transform attachment2)
{
_ropeId = ropeId;
_solver = GetComponentInParent<ObiSolver>();
if (_solver == null)
{
Debug.LogError("No ObiSolver found in parent");
}
_rope = GetComponent<ObiRope>();
_rope.GetComponent<MeshRenderer>().enabled = false;
_blueprint = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
_blueprint.resolution = 1f;
_blueprint.pooledParticles = 100;
_blueprint.thickness = 0.03f;
int filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
Vector3 posCp1 = Vector3.zero;
_cp1Name = $"Rope{_ropeId}_CP1";
Vector3 posCp2 = new Vector3 (-4, 0, 0);
_cp2Name = $"Rope{_ropeId}_CP2";
_blueprint.path.Clear();
_blueprint.path.AddControlPoint(posCp1, Vector3.zero, Vector3.zero, Vector3.up,
ropeMass, ropeRotationalMass, 1f, filter, Color.white, _cp1Name);
_blueprint.path.AddControlPoint(posCp2, Vector3.zero, Vector3.zero, Vector3.up,
ropeMass, ropeRotationalMass, 1f, filter, Color.white, _cp2Name);
_blueprint.path.FlushEvents();
yield return _blueprint.Generate();
_rope.ropeBlueprint = _blueprint;
SetAttachment(attachment1, _cp1Name);
SetAttachment(attachment2, _cp2Name);
yield return null;
_rope.GetComponent<MeshRenderer>().enabled = true;
_rope.ropeBlueprint = _blueprint;
}
private void SetAttachment(Transform attachmentTarget, string particleGroupName)
{
// add a particle attachment to the rope
var particleAttachment = _rope.gameObject.AddComponent<ObiParticleAttachment>();
// disable the attachment
particleAttachment.enabled = false;
// find the particle group we want to attach to
var particleGroup = _rope.ropeBlueprint.groups.Find(x => x.name == particleGroupName);
// set the attachment's particle group to the one we found
particleAttachment.particleGroup = particleGroup;
// get the particle index of the first particle in the group
var particleIndex = particleAttachment.particleGroup.particleIndices[0];
// set the position of that particle to the attachment target
_solver.positions[particleIndex] = _solver.transform.InverseTransformPoint(attachmentTarget.position);
// set the attachment's target to the transform we want to attach to
particleAttachment.target = attachmentTarget;
// re-enable the attachment
particleAttachment.enabled = true;
}
}
and these are instantiated from a system class as follows:
Code: public class RopeSystemIncremental : MonoBehaviour
{
[SerializeField] private Material _ropeMat;
[SerializeField] private Transform _groundAttachmentTra;
[SerializeField] private Transform _playerAttachmentTra;
[SerializeField] private Transform _TESTINGgrabbableAttachmentTra;
[SerializeField] private RopeController _ropePF;
private float _defaultRopeLength = 4f;
private float _ropeMass = 0.1f;
private float _ropeRotationalMass = 0.1f;
private ObiSolver _solver;
private List<RopeController> _ropes = new List<RopeController>();
private void Awake()
{
_solver = GetComponentInChildren<ObiSolver>();
}
[ContextMenu("FirstOne")]
private void FirstOne()
{
InstantiateRope(_groundAttachmentTra, _playerAttachmentTra);
}
[ContextMenu("SecondOne")]
private void SecondOne()
{
InstantiateRope(_TESTINGgrabbableAttachmentTra, _playerAttachmentTra);
}
private RopeController InstantiateRope(Transform attachment1, Transform attachment2)
{
var ropeCont = Instantiate(_ropePF, Vector3.zero, Quaternion.identity, _solver.transform);
_ropes.Add(ropeCont);
ropeCont.gameObject.name = "Rope " + _ropes.Count;
ropeCont.Init(_ropes.Count, _defaultRopeLength, _ropeMass, _ropeRotationalMass, attachment1, attachment2);
return ropeCont;
}
}
Been hitting my head against the wall with this for a while now! Would really appreciate your help. Many thanks in advance.
|
|
|
How to simulate Obi Rope physics? |
Posted by: oleegarch - 21-02-2024, 06:09 PM - Forum: Obi Rope
- Replies (1)
|
|
When i use in unity
Code: Physics.Simulate(Time.fixedDeltaTime);
The Obi Rope is not simulated. Do I understand correctly that Obi Rope need to be simulated in a separate script? If it is true, how i can do this?
I'm developing a game where i need to detect in my server that user actually wins. My full code of simulation process:
Code: private void Start() {
Physics.simulationMode = SimulationMode.Script;
Simulate();
}
private void Simulate() {
GameObject machine = Instantiate(machinePrefab);
MachineController controller = machine.GetComponent<MachineController>();
APIMachineControlStateRequest request = JsonUtility.FromJson<APIMachineControlStateRequest>(json);
controller.SetSimulate(Physics.defaultPhysicsScene);
foreach(MachineControlState state in request.value) {
controller.SetState(state);
Physics.Simulate(Time.fixedDeltaTime);
}
}
When i start it, Obi Rope behave unpredictably
|
|
|
Rope saving and restore |
Posted by: Apoll0 - 20-02-2024, 08:27 AM - Forum: Obi Rope
- Replies (3)
|
|
Hello!
I have this question, I'm making a game where ropes are tied in knots and hold each other. In the first version I tied all the ropes in the editor using blueprints, which I edited and then saved. In this variant the ropes hold each other quite well, even if you try to move them by static attachments. You don't have to move them much, so they don't usually go through each other.
Then I changed to an editor that runs in runtime, and you can tie the ropes by rearranging the attachments. Then I save positions and velocities in json for particles. I also save the position of attachments.
Then I restore them in the real game. First I load prefab, where the ropes are in the initial position, as in the template. Then I restore from json positions and velocities of particles. And positions of the attachments.
The ropes are restored without problems, they look exactly as they should at the beginning. But then the ropes start to hold each other very badly. They hold a little, but at any attempt to move them they start to pass through each other.
Maybe there's something else I'm forgetting to do. Maybe I need to call some method to rebuild some constraints after position and velocity of partials are restored?
This is my code for saving and restoring ropes it is script on the rope object itself. Tip1 and Tip2 - are static attachments
public JSONObject SaveRopeToJSONObject()
{
var solver = _rope.solver;
var particlesIndices = _rope.solverIndices;
var positions = new List<Vector3>();
var velocities = new List<Vector3>();
for (int i = 0; i < particlesIndices.Length; i++)
{
positions.Add(solver.positions[particlesIndices[i]]);
velocities.Add(solver.velocities[particlesIndices[i]]);
}
var positionsArray = new JSONArray();
var velocitiesArray = new JSONArray();
for (int i = 0; i < positions.Count; i++)
{
var p = (JSONNode)positions[i];
positionsArray.Add(p);
var v = (JSONNode)velocities[i];
velocitiesArray.Add(v);
}
var ropeObject = new JSONObject();
ropeObject.Add("Tip1Pos", (JSONNode)_ropeTip1.transform.position);
ropeObject.Add("Tip2Pos", (JSONNode)_ropeTip2.transform.position);
ropeObject.Add("Tip1Rot", (JSONNode)_ropeTip1.transform.rotation.eulerAngles);
ropeObject.Add("Tip2Rot", (JSONNode)_ropeTip2.transform.rotation.eulerAngles);
ropeObject.Add("positions", positionsArray);
ropeObject.Add("velocities", velocitiesArray);
return ropeObject;
}
public void RestoreRopeFromJSONObject(JSONObject ropeObject)
{
_ropeTip1.transform.position = (Vector3)ropeObject["Tip1Pos"];
_ropeTip2.transform.position = (Vector3)ropeObject["Tip2Pos"];
_ropeTip1.transform.rotation = Quaternion.Euler((Vector3)ropeObject["Tip1Rot"]);
_ropeTip2.transform.rotation = Quaternion.Euler((Vector3)ropeObject["Tip2Rot"]);
var ropeParticlesPosition = ropeObject["positions"].AsArray;
var ropeParticlesVelocities = ropeObject["velocities"].AsArray;
var solver = _rope.solver;
var particlesIndices = _rope.solverIndices;
for (int i = 0; i < particlesIndices.Length; i++)
{
solver.positions[particlesIndices[i]] = (Vector3)ropeParticlesPosition[i];
solver.velocities[particlesIndices[i]] = (Vector3)ropeParticlesVelocities[i];
}
}
|
|
|
Rope/rod freezing |
Posted by: stepkka - 17-02-2024, 02:59 PM - Forum: Obi Rope
- Replies (3)
|
|
I need to reset a rope to blueprint and freeze it. In addition, ideally I need to set the rope's parent to some object without a solver. I'm calling ResetParticles, but the rope's shape stays the same as the last frame before this procedure.
So.. can I reset particles and move the rope outside of solver, or this is not recommended? If I can, what other calls should I make to update the visuals of the rope after resetting?
|
|
|
|