Multiple basic questions

#1
Hi. I‘m currently pretty confused with the Game Templates and the new Schematyc system. I hope that someone can clear things up a little for me.
Here is my list of questions that I have:

1. When looking at the templates it seems as if we now create entire games as plugins. If so, how do we add proper .pak encryption? I mean... there is no GameStartup class... This would be the place where we did it until now (inserting the RSA Key). Is it currently better to use the old Game Zero for game projects? Here we have all of our Game, GameStartup, EditorGame and GameFactory classes. We even have GameRules.

2. How do we implement GameRules with the new System? I can only find them in older templates. Is it still the same process? And if so, will there be changes to it in the future? I‘m currelty not sure about how to implement GameRules inside the new templates. Furthermore some more documentation about GameRules and GameModes would be nice, because I also have no real idea about how to implement GameRules with the old templates.

3. If we expose some Variables, Structs or similar to Schematyc, will these values be automatically serialized when creating a savegame? Or how do we serialize? Inside the doc I found multiple functions for this (see here: https://docs.cryengine.com/plugins/serv ... w/29797021)
So do we need to use the GameSerialize function for this purpose? Or is there some kind of auto savegame serialization for values that are exposed to Schematyc?

4. In the old entity system we could easily (with LUA) implement a FlowNode for an entity. However I couldn‘t find anything like that in Schematyc. Is there any way to do so?

5. Also in the old entity system we could easily create states in LUA (by just adding their names as a string to our state table). Then we could easily switch between states and have some logik for entering and leaving the state. I know that Schematyc has a state machine aswell. But can we somehow access it inside of C++? If so, how do we create states? How do we switch between them? How do we react to entering and leaving the state?

6. Is there any good approach about how to implement AI? I know that we have a pathfinder component, factions, MBT, perception, dynamic respone system and so on, but did anyone have any success in actually putting everything together to implement a basic AI? I currently have no idea about how to approach this. Specially about how to make it react to the player (recognize the player, shoot at him or hunt him, recognizes when player is not in sight anymore, etc.). I would really appreciate any help about this.

7. How do we properly pack these Template Games for publishing? I guess that we now need to do proper release builds of all the default components, etc. aswell?

8. If I got this right, then the ForceFeedback system
is part of the Engine itself (found it inside of CryAction). So we should be able to use it inside the Game Templates aswell. The doc about setting it up is pretty well done. However I wonder how we trigger it from C++ code from our game without the need for always using the FFB FlowNodes.

9. How can I create custom MBT elements for AI and how do I register them, so that they can be used inside of MBTs?

10. How can Audio be triggered from C++? Again this was pretty easy inside of LUA.

11. The Dynamic Response System also allwos to define a subtitle for a line. How do we get this subtitle when a sound is played and forward it to our UI?

12. Let‘s say we already have a health system for players and AI. How could we react to a bullet hitting the player (basically speaking: how do we properly react to bullet collision) and how do we get the damage (which is probably stored inside the bullet, that hit the player). Can we somehow get this information through the collision info?



I know that these are a lot of questions. But I hope that someone can clarify all of this for me.
Thanks and have a nice day
- Jannis

Re: Multiple basic questions

#2
10. We can do it by IEntityAudioComponent

Code: Select all

IEntityAudioComponent* pIEntityAudioComponent = GetEntity()->GetOrCreateComponent<IEntityAudioComponent>();

CryAudio::AuxObjectId nAudioProxyID = 0;
nAudioProxyID = m_pIEntityAudioComponent->CreateAudioAuxObject();

m_pIEntityAudioComponent->SetAudioAuxObjectOffset(GetEntity()->GetLocalTM(), nAudioProxyID);

CryAudio::ControlId nTriggerID = CryAudio::StringToId("Play_SoftHit");
if (nTriggerID != 0)
{
m_pIEntityAudioComponent->ExecuteTrigger(nTriggerID);
}
Last edited by hodirt on Tue Oct 16, 2018 11:58 am, edited 1 time in total.

Re: Multiple basic questions

#3
12. related to bullet and applying damage

Code: Select all

/// All thing what may correspont a damage should be derived from this or agregate this class as component
class IDamagable : public IEntityComponent
{
public:

static void ReflectType(Schematyc::CTypeDesc<IUnit>& desc)
{
desc.SetGUID("{9283632C-9F9A-4F4E-B5A8-7FF6F5172B6C}"_cry_guid);
}
public:
virtual float GetDamage() { return 0.0f; };
};


class CBullet : public IDamagable
{
public:

static void ReflectType(Schematyc::CTypeDesc<CBullet>& desc)
{
desc.AddBase<IDamagable>();
desc.SetGUID("{9283632C-9F9A-4F4E-B5A8-7FF6F5172B6C}"_cry_guid);
}
public:
float GetDamage() override { return 1.0f; };

};

class CGranate : public IDamagable
{
public:

static void ReflectType(Schematyc::CTypeDesc<CGranate>& desc)
{
desc.AddBase<IDamagable>();
desc.SetGUID("{1283632C-9F9A-4F4E-B5A8-7FF6F5172B6C}"_cry_guid);
}
public:
float GetDamage() override { return 2.0f; };

};

void CPlayer::CheckForCollision()
{
// OnCollision event checking and getting Entity
IDamagable* component = ent->GetComponent<IDamagable>();
if (component)
{
ApplyDamageForPlayer(component->GetDamage());
}
}
Also don't forget to register all those components, otherwise you wont get it by calling m_pEntity->GetComponent<T>
For non-registred classes(internally classes) what not exposed to schematyc you can try m_pEntity->GetComponentClass<T> but about registering I'am not sure.

Code: Select all

static void RegisterFewComponents(Schematyc::IEnvRegistrar& registrar)
{
Schematyc::CEnvRegistrationScope scope = registrar.Scope(IEntity::GetEntityScopeGUID());
{
Schematyc::CEnvRegistrationScope damagableComponentScope = scope.Register(SCHEMATYC_MAKE_ENV_COMPONENT(IDamagable));
// Functions
{

}

Schematyc::CEnvRegistrationScope bulletManComponentScope = scope.Register(SCHEMATYC_MAKE_ENV_COMPONENT(CBullet));
// Functions
{
}
Schematyc::CEnvRegistrationScope granateManComponentScope = scope.Register(SCHEMATYC_MAKE_ENV_COMPONENT(CGranate));
// Functions
{
}
}
}

CRY_STATIC_AUTO_REGISTER_FUNCTION(&RegisterFewComponents)
Last edited by MoonBeam on Wed Oct 17, 2018 12:54 pm, edited 2 times in total.

Re: Multiple basic questions

#4
10. How can Audio be triggered from C++? Again this was pretty easy inside of LUA.

Hi Jannis,

There are several ways of "executing an audio trigger" via C++ depending on what you want to achieve.

1. play 2D
2. play 3D without explicitly handling the audio object
3. play 3D with explicitly handling the audio object
4. play via an entity (covered by hodirt's reply above)

for 1. (play 2D)

Code: Select all

CryAudio::ControlId const triggerId = CryAudio::StringToId("trigger_name");
gEnv->pAudioSystem->ExecuteTrigger(triggerId);

for 2. (play 3D without explicitly handling the audio object)

Code: Select all

CryAudio::ControlId const triggerId = CryAudio::StringToId("trigger_name");
Vec3 pos(111.0f, 222.0f, 333.0f); // make sure to use proper position
CryAudio::SExecuteTriggerData const triggerData(triggerId, "audio_object_name_for_debugging", CryAudio::EOcclusionType::Ignore, pos, INVALID_ENTITYID, true);
gEnv->pAudioSystem->ExecuteTriggerEx(triggerData);

for 3. (play 3D with explicitly handling the audio object)

Code: Select all

Vec3 pos(111.0f, 222.0f, 333.0f); // make sure to use proper position
CryAudio::SCreateObjectData const objectData("audio_object_name_for_debugging", CryAudio::EOcclusionType::Ignore, pos, INVALID_ENTITYID, true);
CryAudio::IObject* const pIObject = gEnv->pAudioSystem->CreateObject(objectData);
CryAudio::ControlId const triggerId = CryAudio::StringToId("trigger_name");
pIObject->ExecuteTrigger(triggerId);
gEnv->pAudioSystem->ReleaseObject(pIObject);

Re: Multiple basic questions

#5
Many thanks to all three of you. This is really helpful in understanding sound and collision. Thank you all so much. I hope that someone can answer my other questions aswell.
However I‘ll try all of your suggestions this weekend (don‘t have time earlier). Thanks.

Re: Multiple basic questions

#6
4. For now, Schematyc can't fully replace Flowgraph. Maybe in 5.6 with Schematyc 2.0.

I don't know if this is the best approach, but you can create flownode like this

Code: Select all


class CFlowNode_MyFlownode: public CFlowBaseNode<eNCT_Instanced> {

public:
enum EInputPorts
{
eInputPort_EntityId,
};

enum EOutputPorts
{
eOutputPort_Collided
};
CFlowNode_MyFlownode(SActivationInfo *pActInfo) {

}

void Serialize(SActivationInfo * pActInfo, TSerialize ser)
{

}
virtual IFlowNodePtr Clone(SActivationInfo *pActInfo) {
return new CFlowNode_MyFlownode(pActInfo);
}

virtual void GetConfiguration(SFlowNodeConfig &config)
{
static const SInputPortConfig inp_config[] =
{
InputPortConfig<int>("EntityId", ""),

{ 0 }
};

static const SOutputPortConfig out_config[] =
{
OutputPortConfig_AnyType("Collided"),

{ 0 }
};

config.sDescription = _HELP("Collision detector");
config.pInputPorts = inp_config;
config.pOutputPorts = out_config;
config.SetCategory(EFLN_APPROVED);
}

virtual void ProcessEvent(EFlowEvent event, SActivationInfo *pActInfo)
{
pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true); //to update on every frame

switch (event)
{
case eFE_Initialize:
{
}
break;
case eFE_Activate:
{
if (m_pMyComponent = gEnv->pEntitySystem->GetEntity(GetPortInt(pActInfo, eInputPort_EntityId))->GetComponent<CMyComponent>()) {
}
}
break;
case eFE_Update:
{

break;
}
}


virtual void GetMemoryUsage(ICrySizer * s) const
{
s->Add(*this);
}

CMyComponent* m_pMyComponent;

};

REGISTER_FLOW_NODE("Enitities:MyFlownode", CFlowNode_MyFlownode);
And, but I'm not sure, you have to register your nodes in CGamePlugin::OnSystemEvent in ESYSTEM_EVENT_REGISTER_FLOWNODES like this

Code: Select all

if (IFlowSystem* pFlowSystem = gEnv->pFlowSystem)
{
CAutoRegFlowNodeBase* pFactory = CAutoRegFlowNodeBase::s_pFirst;
while (pFactory)
{
pFlowSystem->RegisterType(pFactory->m_szClassName, pFactory);
pFactory = pFactory->m_pNext;
}
}

Re: Multiple basic questions

#7
And, but I'm not sure, you have to register your nodes in CGamePlugin::OnSystemEvent in ESYSTEM_EVENT_REGISTER_FLOWNODES like this
It's seems that Cry::IEnginePlugin have a method for registering/unreginstering custom/user's FlowNodes

Code: Select all

//! Called when the plug-in should register all its flow nodes
//! Automated version can be enabled using the PLUGIN_FLOWNODE_REGISTER macro
virtual bool RegisterFlowNodes() { return false; }
//! Called when the plug-in should unregister all its flow nodes
//! Automated version can be enabled using the PLUGIN_FLOWNODE_UNREGISTER macro
virtual bool UnregisterFlowNodes() { return false; }

Re: Multiple basic questions

#8
4. For now, Schematyc can't fully replace Flowgraph. Maybe in 5.6 with Schematyc
Hi. Thanks for the response. However I should maybe clarify my question, because I already know about FlowNode implementation. What I wanted to ask is this: in Lua we could define an entity flow node for each entity. So e.g. if you have a door entity in your level you could select it, create a Flowgraph and the add the selected entity to the FG.
This means that the door could be managed with FG, because there was an entity FlowNode for it which was defied inside the door‘s LUA script. So everytime we added a LUA entity (which has a custom FG logic), we could easily just use it inside of FG. I wanted to know if there is a way with Schematyc entities to do exactly that. So basically defining a default FlowNode for this entity.

However I don‘t think that Schematyc will replace FG anytime soon. Both are entirely different concepts. This is also handled like this in other engines. When compared e.g. with Unreal, they also have their Blieprints (like Schematyc) and their Level blueprints (like FG). Despite the name and the design, these concepts don‘t share much. One is for Level logic, the other is for Game/Entity Logik.

But still I want to thank you very much for your answer. Every kind of help is welcome ;)

- Jannis

Re: Multiple basic questions

#9
Just wanted to give an update for anyone who faces the same problems that I currently have:

8. ForceFeedback:
I‘ve looked into CryAction and found this piece of code:

Code: Select all

// Stop force feedback IForceFeedbackSystem* pForceFeedbackSystem = gEnv->pGameFramework->GetIForceFeedbackSystem(); if(pForceFeedbackSystem) { pForceFeedbackSystem->StopAllEffects(); }
This shows how we can get the FFB System
Inside of C++. Now when we look into CryAction/ForceFeedbackSystem/ForceFeedbackSystem.h we find this:

Code: Select all

//IForceFeedbackSystem virtual void PlayForceFeedbackEffect(ForceFeedbackFxId id, const SForceFeedbackRuntimeParams& runtimeParams) override; virtual void StopForceFeedbackEffect(ForceFeedbackFxId id) override; virtual void StopAllEffects() override; virtual ForceFeedbackFxId GetEffectIdByName(const char* effectName) const override; virtual void AddFrameCustomForceFeedback(const float amplifierA, const float amplifierB, const float amplifierLT = 0.0f, const float amplifierRT = 0.0f) override; virtual void AddCustomTriggerForceFeedback(const SFFTriggerOutputData& triggersData) override; virtual void EnumerateEffects(IFFSPopulateCallBack* pCallBack) override; // intended to be used only from the editor virtual int GetEffectNamesCount() const override; virtual void SuppressEffects(bool bSuppressEffects) override; //~IForceFeedbackSystem
These are the public functions, that are offered by the FFB System. So basically we can get the FFB Effect Id by its name and then play this effect.

Setting up FFB Effects is well documented (just google „CryEngine Force Feedback“ if anyone doesn‘t know about it).
I‘ll try this code tomorrow. However, I won‘t be able to confirm that everything works, because I don‘t own any controllers (which would play the rumbling effect). But these two pieces of code pretty much clarify how it is done. I guess, that the FFB System will automatocally recognize the xml file if it is placed inside the same folder structure as in the GameSDK project. However I can not confirm
this, because I couldn‘t find it inside the code.
But other systems in CryEngine behave like that, so that I just assume that this is true here aswell.
An example would be the AI Faction system. Here we can find the file path inside the code. So I can confirm that AI Factions are automatically loaded if you placed the xml file inside the correct location.

Hope that this was useful to someone.
Anyways: if anyone else knows anything (specially about AI), I would really appreciate an answer to my other questions.

Have a nice day
- Jannis

EDIT: For more examples on how to use FFB from C++, you can look into CryEngine/CryFlowGraph/FlowSystem/Nodes/FlowInputNode.cpp
This file is not too long and pretty easy to read. You can clearly see here how an effect is played. By the way: For playing an effect you need it‘s id (see the public fuctions above. You can get it by it‘s effect name.) And a stuct with runtime parameters. This struct is defined inside CryAction/IForceFeedbackSystem.h and looks like this:

Code: Select all

struct SForceFeedbackRuntimeParams { SForceFeedbackRuntimeParams() : intensity(1.0f) , delay(0.0f) { } SForceFeedbackRuntimeParams(float _intensity, float _delay) : intensity(_intensity) , delay(_delay) { } float intensity; //Scales overall intensity of the effect (0.0f - 1.0f) float delay; //Start playback delay };
So basically you should be able to use this struct as soon as you include the FFB header file (which imcludes IForceFeedbackSystem.h). The struct only defines two floats (intensity and delay). You can create it with both prameters or without parameters. This would just immediately play the effect with full strength (typically what we want).

Re: Multiple basic questions

#10
3. If we expose some Variables, Structs or similar to Schematyc, will these values be automatically serialized when creating a savegame? Or how do we serialize? Inside the doc I found multiple functions for this (see here: https://docs.cryengine.com/plugins/serv ... w/29797021)
So do we need to use the GameSerialize function for this purpose? Or is there some kind of auto savegame serialization for values that are exposed to Schematyc?
Unfortunately no. The current Schematyc system is not exposed to the save game logic. It would be advised to create your logic in a way that reads data from such systems as GameTokens upon level load to crate your starting state.

4. In the old entity system we could easily (with LUA) implement a FlowNode for an entity. However I couldn‘t find anything like that in Schematyc. Is there any way to do so?

5. Also in the old entity system we could easily create states in LUA (by just adding their names as a string to our state table). Then we could easily switch between states and have some logik for entering and leaving the state. I know that Schematyc has a state machine aswell. But can we somehow access it inside of C++? If so, how do we create states? How do we switch between them? How do we react to entering and leaving the state?
This LUA functionality is not exposed to Schematyc as the Schematyc graphs are to be a considered a complete replacement for LUA based scripting. The idea of the LUA scripts was to allow designers the ability to create and extend functionality in the engine to suit their needs. Now designers can do this visually inside of Schematyc - in Sandbox.

6. Is there any good approach about how to implement AI? I know that we have a pathfinder component, factions, MBT, perception, dynamic respone system and so on, but did anyone have any success in actually putting everything together to implement a basic AI? I currently have no idea about how to approach this. Specially about how to make it react to the player (recognize the player, shoot at him or hunt him, recognizes when player is not in sight anymore, etc.). I would really appreciate any help about this.
This varies from game to game and you would need to use the base AI functions like perception to build your AI logic around. Not every game will tell the AI to shoot the player on sight. I am not an AI designer but the way I see it at the moment these actions are handled by behavior trees. you can read more about the stock AI system in CRYENGINE on our revised documentation at https://docs.cryengine.com/pages/viewpa ... d=25534272

7. How do we properly pack these Template Games for publishing? I guess that we now need to do proper release builds of all the default components, etc. aswell?
CRYENGINE now ships with release binaries. For templates, it should be as easy as right-clicking your project file and selecting "Package build". This will consolidate all the engine binaries and necessary files, as well as packaging your game assets into a single folder that you can redistribute. Depending on what assets you are packaging, you may need to tweak the RC Jobs file to your specific needs. You can find out more about the RC Jobs file in our documentation here:
https://docs.cryengine.com/display/CEMA ... nd+Job+XML

The files in question to modify would be here by default:
C:\Program Files (x86)\Crytek\CRYENGINE Launcher\Crytek\CRYENGINE_5.5\Tools\CryVersionSelector\rc_jobs


I hope this answers most if not the rest of your questions. If you still have questions feel free to ask again.
Uniflare
CRYENGINE Community Coordinator
Here to help the community and social channels grow and thrive.

My personal belongings;
Beginner Guides | My GitHub | Splash Plugin

Who is online

Users browsing this forum: No registered users and 2 guests